Left join with multiple where clause for the first (left table) - php

I got this Query:
$query = mysql_query("SELECT arbejdsopgave.*,
DATE_FORMAT(dato, '%d-%m-%Y') AS tid,
tilfoejelser.*,
DATE_FORMAT(datotf, '%d-%m-%Y') AS tid2
FROM arbejdsopgave LEFT JOIN tilfoejelser
ON arbejdsopgave.sub_id=tilfoejelser.sub_id2
WHERE arbejdsopgave.cat_id = '$id'
AND datotf IS NULL
OR datotf = (select max(datotf)
FROM tilfoejelser
WHERE arbejdsopgave.sub_id=tilfoejelser.sub_id2)
ORDER BY arbejdsopgave.sub_id")
or die(mysql_error());
I need to to only show rows from the table "arbejdsopgave" where arbejdsopgave.cat_id = '$id' but also where arbejdsopgave.status = 'closed'
I tried both in the join on and in the where.
First I get everything despite the extra where. Secondly I get only the rows where there are a join.
Can anyone help me - I am amazed that i even made it this far looking at my Query... Pls help

This should work:
SELECT arbejdsopgave.*, DATE_FORMAT(dato, '%d-%m-%Y') AS tid, tilfoejelser.*, DATE_FORMAT(datotf, '%d-%m-%Y') AS tid2
FROM arbejdsopgave
LEFT JOIN tilfoejelser ON arbejdsopgave.sub_id=tilfoejelser.sub_id2
WHERE arbejdsopgave.cat_id = '$id'
AND arbejdsopgave.status = 'closed'
AND (datotf IS NULL
OR datotf = (
select max(datotf) FROM tilfoejelser
WHERE arbejdsopgave.sub_id=tilfoejelser.sub_id2) )
ORDER BY arbejdsopgave.sub_id
I suppose you forget about () around datotf OR condition

Related

Doctrine query builder inner join with subselect

I have this query in SQL that's working fine:
SELECT tl.*
FROM table1 tl
INNER JOIN table2 tl2
ON tl.id = tl2.other_id
INNER JOIN
(
SELECT other_id, MAX(date) maxDATE
FROM table2
GROUP BY other_id
)
tlv2 ON tl2.other_id = tlv2.other_id AND
tl2.date = tlv2.maxDATE WHERE tl.access=0
ORDER BY tlv2.maxDATE DESC
Now the problem is, I cant seem to figure out how to translate this into the Doctrine query builer.
I have this:
$subquery = $this->getEntityManager()->getRepository(Table2::class)
->createQueryBuilder('tl2')
->select(array('other_id','MAX(date) maxDate'))
->groupBy('other_id')
->getDQL();
$qb = $this->createQueryBuilder('tl');
$qb->select('tl')
->innerJoin(Table2::class,'tl2','WITH','tl.id = tl2.other_id')
->innerJoin("(".$subquery.")",'tlv2','WITH','tl2.date = tlv2.maxDATE')
->where('tl.access = 0')
->orderBy('tlv2.maxDATE','DESC');
but it's giving me the error:
Subquery is not supported here
On the line where I put the $subquery variable.
I cant seem to figure out what I'm doing wrong here. What am I doing wrong?
as mentioned here if you are using the ORM then the mapping will fail, you can only run this without hydration, in case you are using the DBAL only it will work as you expect
If you would go for native query solution and still need a mapped result then you can use \Doctrine\ORM\EntityManager::createNativeQuery with \Doctrine\ORM\Query\ResultSetMapping
$sql = <<<SQL
SELECT tl.*
FROM table1 tl
INNER JOIN table2 tl2
ON tl.id = tl2.other_id
INNER JOIN
(
SELECT other_id, MAX(date) maxDATE
FROM table2
GROUP BY other_id
)
tlv2 ON tl2.other_id = tlv2.other_id AND
tl2.date = tlv2.maxDATE WHERE tl.access=0
ORDER BY tlv2.maxDATE DESC
SQL;
$rsm = new Query\ResultSetMapping();
$rsm->addEntityResult(Entity::class, 'e');
$rsm->addFieldResult('e','id', 'id');
$rsm->addFieldResult('e','date', 'createAt');
$result = $this->entityManager->createNativeQuery($sql, $rsm)->getResult();

Get the last records from 3 tables

My tables
$sql="SELECT *
FROM addresses
LEFT JOIN users ON address_id = user_id
LEFT JOIN notes ON note_id = user_id
ORDER BY id DESC
LIMIT 1";
This is my SQL query, my task is to show the last records from 3 tables, but the table is blank, I don't know why,thanks in advance people :)
I guess the problem is coming from the ORDER BY id DESC .
Indeed, you have no column so called id.
You should probably remove this clause, in order to make your code work.
If you want to take the last records anyway, you can put an ORDER BY address_id DESC which will do the job !
The code directly edited :
$sql="SELECT *
FROM addresses
LEFT JOIN users ON address_id = user_id
LEFT JOIN notes ON note_id = user_id
ORDER BY adress_id DESC
LIMIT 1";
This may work:
SELECT a.address_id, u.user_id, n.note_id
FROM addresses a
LEFT JOIN users_addresses ua ON ua.ua_address_id = a.address_id
LEFT JOIN users u ON u.user_id = ua.ua_user_id
LEFT JOIN notes n ON n.note_user_id = u.user_id
ORDER BY a.address_id DESC
LIMIT 1
Here is the query to get all data from all the tables, not sure what do you mean last records from 3 tables, I can see four tables there:
SELECT *
FROM `addresses`
LEFT JOIN `users_addresses` ON `users_addresses`.`ua_address_id` = `addresses`.`address_id`
LEFT JOIN `users` ON `users`.`user_id` = `users_addresses`.`ua_user_id`
LEFT JOIN `notes` ON `notes`.`note_user_id` = `users`.`user_id`;

I want to show only that data which has date is null

I want to show only that data which date is null
Here is my query:
$Query = "SELECT att.`EmployeeCode`,emp.FullName ,emp.EmployeeID,emp.Photo,sum(TIME_TO_SEC(att.FinalTime)/60 - IFNULL(sp.TotalTimeLateMark,$TotalTimeLateMark)) OverTime
FROM `hr_tblattendancehistory` att
left join hr_tblemployee emp on att.EmployeeCode = emp.CardID
left join hr_tblspecialattendancesetting sp on sp.Date = att.Date
WHERE emp.FullName!='' and att.`Date` Between '$FromDate' and '$Todate=''' and (TIME_TO_SEC(att.FinalTime)/60 -IFNULL(sp.TotalTimeLateMark,$TotalTimeLateMark)) > 0
group by att.`EmployeeCode`,emp.Photo,emp.FullName
order by SUM(TIME_TO_SEC(att.FinalTime)/60 -IFNULL(sp.TotalTimeLateMark,$TotalTimeLateMark)) DESC";
How can I do this ?
You can use IS NULL
e.g.
SELECT * FROM YourTable WHERE DateColumn IS NULL;
In your particular case you are probably looking for IS NULL, just like Nilesh Thakkar has pointed out. But in the HAVING clause:
SELECT * FROM YourTable A
LEFT JOIN AnotherTable B on A.DateColumn=B.DateColumn
HAVING DateColumn IS NULL;
That is because the selection should happen after the join, not before.

Mysql group_concat with distinct and where gives strange results

I have the following query which works fine (see below).
But when I add a condition, for example AND (specialtyName = '...') the main results are fine, but the GROUP_CONCAT only shows the results that match the condition.
Can anyone please help me with this?
Thanks in advance.
Fred.
SELECT
tblJobs.jobID,
tblJobs.jobName,
DATE_FORMAT(tblJobs.jobDate,'%d-%m-%Y'),
tblCompanies.companyID,
tblCompanies.companyName,
tblCompanies.companyNameConvert,
GROUP_CONCAT(DISTINCT tblSpecialties.specialtyName
ORDER BY FIELD (
specialtyName,
'specialtyName1',
'specialtyName2',
'specialtyName3'),
specialtyName ASC)
AS specialtyNames,
GROUP_CONCAT(DISTINCT tblSpecialties.specialtyNameConvert
ORDER BY FIELD (
specialtyName,
'specialtyName1',
'specialtyName2',
'specialtyName3'),
specialtyName ASC)
AS specialtyNamesConvert,
GROUP_CONCAT(DISTINCT tblRegions.regionName),
GROUP_CONCAT(DISTINCT tblRegions.regionNameConvert)
FROM tblJobs
LEFT JOIN tblCompanies ON
(tblJobs.jobCompany = tblCompanies.companyID)
LEFT JOIN tblSpecialties ON
FIND_IN_SET(tblSpecialties.specialtyID, REPLACE(tblJobs.jobSpecialty,' ',','))
LEFT JOIN tblRegions ON
FIND_IN_SET(tblRegions.regionID, REPLACE(tblJobs.jobRegion,' ',','))
WHERE
AND jobActive = '1'
AND jobDate >= '2013-01-01'
AND companyActive = '1'
GROUP BY jobID
ORDER BY jobDate DESC, jobID DESC, jobCompany DESC
If you say:
WHERE jobActive = '1' AND jobDate >= '2013-01-01' AND companyActive = '1' AND
specialties = XXX
Then you are only going to get exactly those specialties. The filtering is done before the aggregation. As a note: including such conditions in the where clause also turns the outer joins to inner joins. Your joins are probably on properly aligned foreign key relationships, so inner joins may be appropriate.
I'm guessing what you really want is to filter jobs by those having that specialty, but to keep all other information. You want to do the filtering after the aggregation. Do this with a having clause instead of a where clause:
having sum(specialties = XXX) > 0;
This will keep only the rows that have the particular specialty, and keep all the other information.
I suppose that using aliases for your tables and subqueries could resolve your problem.
You can try something like this:
SELECT
tblJobs.jobID,
tblJobs.jobName,
DATE_FORMAT(tblJobs.jobDate,'%d-%m-%Y'),
tblCompanies.companyID,
tblCompanies.companyName,
tblCompanies.companyNameConvert,
(SELECT GROUP_CONCAT(DISTINCT ts.specialtyName
ORDER BY FIELD (
specialtyName,
'specialtyName1',
'specialtyName2',
'specialtyName3'),
specialtyName ASC)
FROM tblSpecialties ts) AS specialtyNames ,
, ... ,
FROM tblJobs
LEFT JOIN tblCompanies ON
(tblJobs.jobCompany = tblCompanies.companyID)
LEFT JOIN tblSpecialties ON
FIND_IN_SET(tblSpecialties.specialtyID, REPLACE(tblJobs.jobSpecialty,' ',','))
LEFT JOIN tblRegions ON
FIND_IN_SET(tblRegions.regionID, REPLACE(tblJobs.jobRegion,' ',','))
WHERE
AND jobActive = '1'
AND jobDate >= '2013-01-01'
AND companyActive = '1'
GROUP BY jobID
ORDER BY jobDate DESC, jobID DESC, jobCompany DESC
I didn't tested this code, but It could help.

MYSQL JOIN on multiple tables returning no results

Well let's see, the query I have is working fine, as soon as a friendpost is done, however. If the user has no friends, no result will be returned, and that's what I am trying to get a hang of...
$query = "SELECT DISTINCT m.id, p.byuser, p.`newpost`, p.`id`, p.`postdate`
FROM users m
JOIN pinnwand p
ON m.id = p.byuser
JOIN friends f
ON f.`userid` = m.id OR f.`friendid` = m.id
WHERE (f.`userid` = $myId OR f.`friendid`= $myId)
AND (p.`touser` = p.`byuser` OR p.`touser` = $myId)
AND p.`publicp` < 3
AND p.`typ` = 2
ORDER BY p.id DESC LIMIT $limit, 10";
I hope somebody can help me, maybe I am just blind for nao...
Edit
As Steven helped me out quite a lot, maybe somebody finds the last bit missing: It's just showing the posts made for the specific user. Even though as I understand the query it should get the posts made by friends on their pinboard as well? After all the m.id should get the friendtables value as well, or am I wrong?
Edit 2
So as I went with the UNION and Subquery Method for now, I still want to describe what the result should look like:
Show: Userposts made whereever, Posts by whomever made on the Userboard, Friendposts made on their own board! Not the posts made by people on friends boards.
There are 2 problems:
You need a LEFT JOIN on friends. A LEFT JOIN says to return all records from the first table in the join even if there are no results found in the second table in the join.
You also should the WHERE clause conditions relating to friends into the LEFT JOIN clause, so that the conditions occur at the join. You should also be using m.id wherever possible in your joins instead of $myId to eliminate redundancy.
Your WHERE clause is too restrictive (redundant conditions). Always use the simplest set of conditions possible, and put as many as appropriate at the JOIN so they are easier to read.
Example (Edited to add posts from friends, as well):
$query = "SELECT DISTINCT `u`.`id`, `p`.`byuser`, `p`.`newpost`, `p`.`id`, `p`.`postdate`
FROM `users` AS `u`
LEFT JOIN `friends` AS `f`
ON `f`.`userid` = `u`.`id`
OR `f`.`friendid` = `u`.`id`
JOIN `pinnwand` AS `p`
/* This will get all posts made by the user */
ON `p`.`byuser` = `u`.`id`
/* This will get all posts made TO the user by friends */
OR (`p`.`byuser` IN (`f`.`userid`, `f`.`friendid`)
AND `p`.`touser` = `u`.`id`)
WHERE `u`.`id` = {$myId}
AND `p`.`publicp` < 3
AND `p`.`typ` = 2
ORDER BY `p`.`id` DESC
LIMIT {$limit}, 10";
OK, so in the end i ended up using an Union and a subquery... It's probably suboptimal, but if somebody has a good suggestion what to improve, please give me your opinion! Otherwhise I hope that this post will help people with simmilar problems.
$query = "SELECT DISTINCT `p`.`byuser`, `p`.`newpost`, `p`.`id`, `p`.`postdate`
FROM `pinnwand` AS `p`
JOIN `users` AS `u` ON `u`.`id` = `p`.`byuser`
LEFT JOIN `friends` AS `f` ON (`f`.`friendid` = `u`.`id` OR `f`.`userid` = `u`.`id`)
WHERE (f.userid = {$myId} OR f.friendid = {$myId})
AND `p`.`publicp` < 3
AND `p`.`typ` = 2
AND `p`.`byuser` <> {$myId}
UNION ALL
SELECT DISTINCT `p`.`byuser`, `p`.`newpost`, `p`.`id`, `p`.`postdate`
FROM `pinwand` AS `p`
JOIN `users` AS `u` ON `u`.id = `p`.`byuser`
WHERE `u`.`id` = {$myId}
AND `p`.`publicp` < 3
AND `p`.`typ` = 2
ORDER BY `postdate` DESC
LIMIT 0,10";

Categories