MySQL statement not including Null values [duplicate] - mysql

This question already has answers here:
Left Outer Join doesn't return all rows from my left table?
(3 answers)
Closed 2 years ago.
SELECT DISTINCT
CAST(`t1`.`ImportedOn` AS DATE) AS `DispatchDate`,
`t1`.`Order` AS `order`,
`t1`.`Operation` AS `QbOP`,
`t1`.`UserOpStatus` AS `OpsAway`,
`t1`.`UnloadingPoint` AS `Location`,
`t1`.`WorkCenter` AS `QbWC`,
`t1`.`LatestStartDate` AS `QbStartDay`,
`t1`.`LatestStartTime` AS `QbStartTime`,
`t2`.`Operation` AS `RcOP`,
`t2`.`WorkCenter` AS `RcWC`,
`t2`.`LatestStartDate` AS `lateststartdate`,
`t2`.`LatestStartTime` AS `lateststarttime`,
`wc`.`CellName` AS `CellName`,
IF((`wooc`.`ConfirmationDate` IS NULL),
'Open',
IF((`t1`.`UserOpStatus` = 'run'),
'Running',
'Done')) AS `Status`
FROM
(((`workorderoperationschedule` `t1`
LEFT JOIN `workorderoperationschedule` `t2` ON (((`t1`.`Order` = `t2`.`Order`)
AND (`t2`.`Operation` > `t1`.`Operation`)
AND (`t2`.`Operation` < (`t1`.`Operation` + 11)))))
LEFT JOIN `workcenters` `wc` ON ((`wc`.`WorkCenter` = `t1`.`WorkCenter`)))
LEFT JOIN `workorderoperationconfirmations` `wooc` ON (((`wooc`.`Order` = `t1`.`Order`)
AND (`wooc`.`Operation` = `t1`.`Operation`))))
WHERE
((`t1`.`LatestStartDate` <= CAST(`t1`.`ImportedOn` AS DATE))
AND (`t1`.`ImportedOn` = (SELECT
MAX(`t1`.`ImportedOn`)
FROM
`workorderoperationschedule` `t1`))
AND (`t2`.`ImportedOn` = (SELECT
MAX(`t1`.`ImportedOn`)
FROM
`workorderoperationschedule` `t1`)))
ORDER BY `Status` DESC , `t1`.`WorkCenter` , `t2`.`LatestStartDate` , `t2`.`LatestStartTime`
My challenge is that sometimes t2 will not have a value, which is expected, however, i think MySQL is not returning those rows when t2 has not match. I thought a left join would return all values from t1 and only the values from t2 that match but that is not happening

If you need a left join then you can't use a colunm of a left joined table in a where condition so try move the t2 condition for max value in the related ON clause
SELECT DISTINCT
CAST(`t1`.`ImportedOn` AS DATE) AS `DispatchDate`,
`t1`.`Order` AS `order`,
`t1`.`Operation` AS `QbOP`,
`t1`.`UserOpStatus` AS `OpsAway`,
`t1`.`UnloadingPoint` AS `Location`,
`t1`.`WorkCenter` AS `QbWC`,
`t1`.`LatestStartDate` AS `QbStartDay`,
`t1`.`LatestStartTime` AS `QbStartTime`,
`t2`.`Operation` AS `RcOP`,
`t2`.`WorkCenter` AS `RcWC`,
`t2`.`LatestStartDate` AS `lateststartdate`,
`t2`.`LatestStartTime` AS `lateststarttime`,
`wc`.`CellName` AS `CellName`,
IF((`wooc`.`ConfirmationDate` IS NULL),
'Open',
IF((`t1`.`UserOpStatus` = 'run'),
'Running',
'Done')) AS `Status`
FROM
(((`workorderoperationschedule` `t1`
LEFT JOIN `workorderoperationschedule` `t2` ON (((`t1`.`Order` = `t2`.`Order`)
AND (`t2`.`Operation` > `t1`.`Operation`)
AND (`t2`.`Operation` < (`t1`.`Operation` + 11)))))
AND (`t2`.`ImportedOn` = (SELECT
MAX(`t1`.`ImportedOn`)
FROM
`workorderoperationschedule` `t1`))
LEFT JOIN `workcenters` `wc` ON ((`wc`.`WorkCenter` = `t1`.`WorkCenter`)))
LEFT JOIN `workorderoperationconfirmations` `wooc` ON (((`wooc`.`Order` = `t1`.`Order`)
AND (`wooc`.`Operation` = `t1`.`Operation`))))
WHERE
((`t1`.`LatestStartDate` <= CAST(`t1`.`ImportedOn` AS DATE))
AND (`t1`.`ImportedOn` = (SELECT
MAX(`t1`.`ImportedOn`)
FROM
`workorderoperationschedule` `t1`))
AND (`t2`.`ImportedOn` = (SELECT
MAX(`t1`.`ImportedOn`)
FROM
`workorderoperationschedule` `t1`)))
ORDER BY `Status` DESC , `t1`.`WorkCenter` , `t2`.`LatestStartDate` , `t2`.`LatestStartTime`
WHERE
((`t1`.`LatestStartDate` <= CAST(`t1`.`ImportedOn` AS DATE))
AND (`t1`.`ImportedOn` = (SELECT
MAX(`t1`.`ImportedOn`)
FROM
`workorderoperationschedule` `t1`))
)

The predicate:
`t2`.`ImportedOn` = (SELECT MAX(`t1`.`ImportedOn`)
FROM `workorderoperationschedule` `t1`)
in the WHERE clause is silently converting your LEFT JOIN into an INNER JOIN.
To make the left join work you need to move this predicate to the ON clause when joinining t2.

Related

Sequelize: Force left join on nested subquery which is produced by limit

Hello I have this query generated by sequelize
`Orders` .*,
`OrderPriority`.`id` as `OrderPriority.ID`,
`OrderPriority`.`priority` as `OrderPriority.priority`,
`Employees`.`employee_alias` as `Employees.alias`,
`Employees`.`employee_id` as `Employees.ID` from
(
select
`Orders`.`id` as `ID`,
`Orders`.`due_date` as `dueDate`,
`Orders`.`creation_date` as `creationDate`,
`Orders`.`priority_id` as `priorityID`,
`OrderStatus`.`id` as `OrderStatus.ID`,
`OrderStatus`.`status` as `OrderStatus.status`
from
`orders` as `Orders`
inner join `statuses` as `OrderStatus` on
`Orders`.`status_id` = `OrderStatus`.`id`
where
(`Orders`.`creation_date` >= '2022-07-06 00:00:00'
and `Orders`.`creation_date` < '2022-07-14 00:00:00')
order by
`Orders`.`creation_date` desc
limit 0,
50) as `Orders`
left outer join `order_priorities` as `OrderPriority` on
`Orders`.`priorityID` = `OrderPriority`.`id`
left outer join ( `order_employees` as `Employees->OrderEmployees`
inner join `employes` as `Employees` on
`Employees`.`employee_id` = `Employees->OrderEmployees`.`employee_id`
and (`Employees->OrderEmployees`.`state` = 'Pending'
or `Employees->OrderEmployees`.`state` = 'Accepted')) on
`Orders`.`ID` = `Employees->OrderEmployees`.`order_id`
order by
`creationDate` desc;
I need to filter by null priority but the generated query has priority on the outer query if required:false which is logically wrong and the only way that I found to put the priority inside the subquery is to use required:true but this results in an inner join and I want left join in order to take the null values. Is there a way to force the include as left join inside the subquery?The nested subquery is generated because it exists a many to many relationship between Orders and Employees and limit must be applied to orders. I want to generate the following Query:
`Orders` .*,
`OrderPriority`.`id` as `OrderPriority.ID`,
`OrderPriority`.`priority` as `OrderPriority.priority`,
`Employees`.`employee_alias` as `Employees.alias`,
`Employees`.`employee_id` as `Employees.ID` from
(
select
`Orders`.`id` as `ID`,
`Orders`.`due_date` as `dueDate`,
`Orders`.`creation_date` as `creationDate`,
`Orders`.`priority_id` as `priorityID`,
`OrderStatus`.`id` as `OrderStatus.ID`,
`OrderStatus`.`status` as `OrderStatus.status`
from
`orders` as `Orders`
inner join `statuses` as `OrderStatus` on
`Orders`.`status_id` = `OrderStatus`.`id`
left outer join `order_priorities` as `OrderPriority` on
`Orders`.`priorityID` = `OrderPriority`.`id`
where
(`Orders`.`creation_date` >= '2022-07-06 00:00:00'
and `Orders`.`creation_date` < '2022-07-14 00:00:00' and `Orders`.`priorityID` is null)
order by
`Orders`.`creation_date` desc
limit 0,
50) as `Orders`
left outer join ( `order_employees` as `Employees->OrderEmployees`
inner join `employes` as `Employees` on
`Employees`.`employee_id` = `Employees->OrderEmployees`.`employee_id`
and (`Employees->OrderEmployees`.`state` = 'Pending'
or `Employees->OrderEmployees`.`state` = 'Accepted')) on
`Orders`.`ID` = `Employees->OrderEmployees`.`order_id`
order by
`creationDate` desc;

group and order in mysql

I have to write a query in which I need the given output.
I tried different queries but didn't work.
Actual data :
and I need Output like :
Queries like :
SELECT VCD.id,VCD.effective_date, `VCD`.`charge_id`, `C`.`head`,
`VCD`.`per`, `VCD`.`currency`, `VCD`.`amount`, `VCD`.`remarks`
FROM `vendor_charge` `VC` INNER JOIN `vendor_charge_details` `VCD`
ON `VC`.`id` = `VCD`.`vc_id` LEFT JOIN `charges` `C`
ON `C`.`id` = `VCD`.`charge_id`
WHERE `VC`.`vendor_id` = '12' AND `VCD`.`effective_date` <= '2018-05-22'
GROUP BY `VCD`.`charge_id`, `VCD`.`per`, `VCD`.`currency`
ORDER BY `C`.`head` DESC
and
SELECT VCD.id,VCD.effective_date, `VCD`.`charge_id`, `C`.`head`,
`VCD`.`per`, `VCD`.`currency`, `VCD`.`amount`, `VCD`.`remarks`
FROM `vendor_charge` `VC` INNER JOIN `vendor_charge_details` `VCD`
ON `VC`.`id` = `VCD`.`vc_id` LEFT JOIN `charges` `C`
ON `C`.`id` = `VCD`.`charge_id`
WHERE `VC`.`vendor_id` = '12' AND `VCD`.`effective_date` <= '2018-05-22'
GROUP BY `VCD`.`charge_id`, `VCD`.`per`, `VCD`.`currency`
ORDER BY `VCD`.`effective_date` DESC
I think all you need here is an additional join to a subquery which finds the latest effective_date for each charge_id:
SELECT
VCD.id,
VCD.effective_date,
VCD.charge_id,
C.head,
VC.per,
VCD.currency,
VCD.amount,
VCD.remarks
FROM vendor_charge VC
INNER JOIN vendor_charge_details VCD
ON VC.id = VCD.vc_id
INNER JOIN
(
SELECT charge_id, MAX(effective_date) AS max_effective_date
FROM vendor_charge_details
GROUP BY charge_id
) t
ON VCD.charge_id = t.charge_id AND VCD.effective_date = t.max_effective_date
LEFT JOIN charges C
ON C.id = VCD.charge_id
WHERE VC.vendor_id = '12' AND VCD.effective_date <= '2018-05-22'
ORDER BY
C.head DESC;

Use where clause in temporary table

I am trying to use where clause in temporary table. Actually i used it but results aren't true. trying to find products between 2 dates but when i use where clause it gets no data.
CREATE TABLE #TEMPCOZGU
(
ROW INT,
TEZGAH VARCHAR(50),
COZGU VARCHAR(50),
PERSONEL VARCHAR(50),
DATE DATETIME,
FIRE INT,
FIRE_METRE NUMERIC(25,6)
)
INSERT INTO #TEMPCOZGU
select row_number() over(order by TEZGAH) AS ROW, TEZGAH, COZGU, PERSONEL, TARIH, FIRE, FIRE_METRE
from cozgu_fırelerı
where tezgah = 'M01' and cozgu = 'SAĞ ALT BAĞLANTI'
SELECT T1.TEZGAH, T1.COZGU, T1.PERSONEL,T1.FIRE, T1.FIRE_METRE, t1.DATE, T2.DATE AS PREVIOUSDATE, ISNULL(DATEDIFF(DAY, T2.DATE, T1.DATE), 0) AS GUNFARKI , SUM(MKARE) AS TOPLAMMKARE
FROM #TEMPCOZGU as t1
left outer join #TEMPCOZGU as t2 on t1.row-1 = t2.row
left outer join HALI_TEZGAH AS TE ON T1.TEZGAH = TE.TEZGAH_NO
LEFT OUTER JOIN HALI_GUNLUK_URETIM AS U ON U.TEZGAH = TE.ID
--WHERE U.TARIH BETWEEN T1.TARIH AND T2.TARIH
GROUP BY T1.TEZGAH, T1.COZGU, T1.PERSONEL, T1.DATE,T1.FIRE, T1.FIRE_METRE, T2.DATE
drop table #TEMPCOZGU`
If the datetime values always have the time set to "00:00:00", try
SELECT T1.TEZGAH, T1.COZGU, T1.PERSONEL,T1.FIRE, T1.FIRE_METRE, t1.DATE, T2.DATE AS PREVIOUSDATE, ISNULL(DATEDIFF(DAY, T2.DATE, T1.DATE), 0) AS GUNFARKI , SUM(MKARE) AS TOPLAMMKARE
FROM #TEMPCOZGU as t1
left outer join #TEMPCOZGU as t2 on t1.row-1 = t2.row
left outer join HALI_TEZGAH AS TE ON T1.TEZGAH = TE.TEZGAH_NO
LEFT OUTER JOIN HALI_GUNLUK_URETIM AS U ON U.TEZGAH = TE.ID
WHERE U.TARIH >= T1.TARIH AND U.TARIH < DateADD (T2.TARIH, INTERVAL 1 DAY)
GROUP BY T1.TEZGAH, T1.COZGU, T1.PERSONEL, T1.DATE,T1.FIRE, T1.FIRE_METRE, T2.DATE
If that's not the case, then your between should have worked in the first place.

MySQL error: duplicate column

I'm having a bit of a problem with the following MySQL query and I can't find the source of it.
MySQL tells me that
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name
'annonce_dispo_id'
SELECT MAX(max_price) AS `max_price`,
COUNT(*) AS `nb_annonces`,
SUM(nb_dispo) AS `nb_dispo`
FROM
(SELECT `annonce`.`id`,
CEIL(MAX(price)*1.16) AS `max_price`,
COUNT(DISTINCT annonce.id) AS `nb_annonces`,
COUNT(annonce_dispoo.annonce_dispo_id) AS `nb_dispo`,
`annonce_dispo1`.*,
`annonce_dispo2`.*
FROM `annonce`
LEFT JOIN `annonce_dispo` AS `annonce_dispoo` ON (annonce_dispoo.annonceId = annonce.id
AND STR_TO_DATE(annonce_dispoo.dispo_date, '%d/%m/%Y') >= CURDATE())
INNER JOIN `annonce_dispo` AS `annonce_dispo1` ON annonce.id = annonce_dispo1.annonceId
INNER JOIN `annonce_dispo` AS `annonce_dispo2` ON annonce.id = annonce_dispo2.annonceId
WHERE ((annonce.city IN
(SELECT `cities`.`id`
FROM `cities`
WHERE (cities.label LIKE 'lyon%'))
OR annonce.zipcode = 'lyon')
OR (annonce.city LIKE '28674'
OR annonce.zipcode = '28674'))
AND (annonce_dispo1.dispo_date = '27/05/2014')
AND (annonce_dispo1.disponibility = 'available')
AND (annonce_dispo2.dispo_date = '31/05/2014')
AND (annonce_dispo2.disponibility = 'available')
AND (annonce.visible = 1)
AND (annonce.completed = 1)
GROUP BY `annonce`.`id` HAVING (nb_dispo >= 1)) AS `t`
I thought gave a different alias for the table in each JOIN I use them in, and can't really put my finger on what else is possible to output such an error.
Don't select annonce_dispo1.* and annonce_dispo2.* in your subquery, duplicated column names are being returned. Instead select the fields you need and alias accordingly.
SELECT MAX(max_price) AS `max_price`,
COUNT(*) AS `nb_annonces`,
SUM(nb_dispo) AS `nb_dispo`
FROM
(SELECT `annonce`.`id`,
CEIL(MAX(price)*1.16) AS `max_price`,
COUNT(DISTINCT annonce.id) AS `nb_annonces`,
COUNT(annonce_dispoo.annonce_dispo_id) AS `nb_dispo`,
`annonce_dispo1`.field, `annonce_dispo1`.otherfield,
`annonce_dispo1`.field as field2, `annonce_dispo1`.otherfield as otherfield2
FROM `annonce`
LEFT JOIN `annonce_dispo` AS `annonce_dispoo` ON (annonce_dispoo.annonceId = annonce.id
AND STR_TO_DATE(annonce_dispoo.dispo_date, '%d/%m/%Y') >= CURDATE())
INNER JOIN `annonce_dispo` AS `annonce_dispo1` ON annonce.id = annonce_dispo1.annonceId
INNER JOIN `annonce_dispo` AS `annonce_dispo2` ON annonce.id = annonce_dispo2.annonceId
WHERE ((annonce.city IN
(SELECT `cities`.`id`
FROM `cities`
WHERE (cities.label LIKE 'lyon%'))
OR annonce.zipcode = 'lyon')
OR (annonce.city LIKE '28674'
OR annonce.zipcode = '28674'))
AND (annonce_dispo1.dispo_date = '27/05/2014')
AND (annonce_dispo1.disponibility = 'available')
AND (annonce_dispo2.dispo_date = '31/05/2014')
AND (annonce_dispo2.disponibility = 'available')
AND (annonce.visible = 1)
AND (annonce.completed = 1)
GROUP BY `annonce`.`id` HAVING (nb_dispo >= 1)) AS `t`
See here for an example that doesn't work:
http://sqlfiddle.com/#!2/9bb13/1
The problem is that you are selecting all columns in the tables annonce_dispo1 and annonce_dispo2.
The fact that you have attributed different table names doesn't mean that there aren't duplicate column names.
I mean, you should use [Table name].[column name]
Example:
(SELECT `annonce`.`id`,
CEIL(MAX(price)*1.16) AS `max_price`,
COUNT(DISTINCT annonce.id) AS `nb_annonces`,
COUNT(annonce_dispoo.annonce_dispo_id) AS `nb_dispo`,
`annonce_dispo1`.annonce_dispo_id AS `column1`,
`annonce_dispo2`.annonce_dispo_id AS `column2`
I hope I've helped

How to optimize for speed a sql multiple select with SUM

I have a really long select from my database with many joins. The problem is with counting SUM: without sum, select time is about 3s, but with SUM is about 15s.
Is it possible to optimize my select to obtain a shorter select time?
Here is my code:
SELECT
accomodation.id,
accomodation.aid,
accomodation.title_en,
accomodation.title_url_en,
accomodation.address,
accomodation.zip,
accomodation.stars,
accomodation.picture,
accomodation.valid_from,
accomodation.valid_to,
accomodation.latitude,
accomodation.longitude,
accomodation.city_id AS
accomodation_city_id,
db_cities.id AS city_id,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_en AS country_title,
db_countries.title_url_en AS country_url,
accomodation_type.class AS accomodation_type_class,
accomodation_review_value_total.value AS review_total,
MIN(accomodation_price.price) AS price_from,
accomodation_rooms.total_persons
FROM
(SELECT aid, MAX(info_date_add) AS max_info_date_add FROM accomodation GROUP BY aid) accomodation_max
INNER JOIN accomodation
ON
accomodation_max.aid = accomodation.aid AND
accomodation_max.max_info_date_add = accomodation.info_date_add
LEFT JOIN db_cities
ON (
db_cities.id = accomodation.city_id OR
(((acos(sin((db_cities.latitude*pi()/180)) * sin((accomodation.latitude*pi()/180)) + cos((db_cities.latitude*pi()/180)) * cos((accomodation.latitude*pi()/180)) * cos(((db_cities.longitude - accomodation.longitude)*pi()/180))))*180/pi())*60*1.1515*1.609344) < '20')
JOIN db_countries
ON db_countries.id = accomodation.country_id
LEFT JOIN accomodation_review_value_total
ON accomodation_review_value_total.accomodation_aid = accomodation.aid
LEFT JOIN accomodation_type_value
ON accomodation_type_value.accomodation_id = accomodation.id
LEFT JOIN accomodation_type
ON accomodation_type.id = accomodation_type_value.accomodation_type_id
JOIN accomodation_season
ON (
accomodation_season.accomodation_aid = accomodation.aid AND
( '2013-11-04' BETWEEN accomodation_season.start_date AND accomodation_season.end_date OR '2013-11-05' BETWEEN accomodation_season.start_date AND accomodation_season.end_date ) )
JOIN accomodation_price
ON
accomodation_price.accomodation_aid = accomodation.aid AND
accomodation_price.accomodation_price_type_id = '1' AND
accomodation_price.accomodation_price_cat_id = '1' AND
accomodation_price.price BETWEEN '20' AND '250' AND
accomodation_price.accomodation_season_id = accomodation_season.id
JOIN accomodation_theme_value
ON accomodation_theme_value.accomodation_id = accomodation.id
INNER JOIN
(SELECT
accomodation_id,
SUM(accomodation_rooms.rooms) AS total_rooms,
SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons
FROM accomodation_rooms
GROUP BY accomodation_id) accomodation_rooms
ON
accomodation_rooms.accomodation_id = accomodation.id AND
accomodation_rooms.total_persons >= '4'
WHERE
db_countries.title_url_en LIKE '%spain%' AND
db_cities.title_url LIKE '%barcelona%' AND
accomodation_type_value.accomodation_type_id IN (5,10) AND
total_rooms >= '2' AND
accomodation_theme_value.accomodation_theme_id IN (11,12,13) AND
accomodation.stars IN (3,4,5) AND
( accomodation_review_value_total.value >= '4.5' ) AND
db_cities.id = '2416'
GROUP BY accomodation.aid
ORDER BY
CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW() AND MIN(accomodation_price.price) IS NOT NULL THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to>'0000-00-00' AND MIN(accomodation_price.price) IS NOT NULL THEN 1
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW() THEN 2
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to>'0000-00-00' THEN 3
ELSE 4 END,
review_total DESC,
accomodation.title_en
LIMIT 10