I'm building a report that counts how many materials like my search marked as % below are in locations (Stor.bin) and then joining it to my bins table which has each Stor.bin total capacity. If I remove the inner join my count for Stor.bin is correct but as soon as I add in my join it makes my Totals count completely wrong.
I can't work out why the join is changing my Total count.
SELECT *
FROM (
SELECT COUNT(
CASE
WHEN `SDON`.`Material` LIKE '%' THEN 1
END
) AS `MaterialCount`,
COUNT(`SDON`.`Material`) AS `Total`,
COUNT(DISTINCT `SDON`.`Material`) AS `Materials`,
`SDON`.`Stor.bin`,
`bins`.`Capacity` AS `Bin Capacity`,
(`bins`.`Capacity` - COUNT(`SDON`.`Stor.bin`)) AS `Free Space`
FROM `jjezuk_StockFiles`.`SDON`
INNER JOIN `jjezuk_StockFiles`.`bins` ON `SDON`.`Stor.bin` = `bins`.`Stor.bin`
WHERE `SDON`.`import_date` = "2022-10-05"
AND `C` != 'Q'
AND `C` != 'T'
AND `C` != 'A'
AND `C` != 'S'
GROUP BY `SDON`.`Stor.bin`
) XYZ
WHERE `MaterialCount` > 0
ORDER BY `XYZ`.`Total` DESC
Related
Hi I am trying to query a table that conatains multiple duplicates on Code,Amount and Status How will I do this if I only one to get a result group according to the client_group name and get the sum of amount under that group
SELECT `client`.`client_group`
, FORMAT(SUM(`Data_result`.`Data_result_amount` ),2) as sum
FROM
`qwer`.`Data_result`
INNER JOIN `qwer`.`Data`
ON (`Data_result`.`Data_result_lead` = `Data`.`Data_id`)
INNER JOIN `qwer`.`Data_status`
ON (`Data_result`.`Data_result_status_id` = `Data_status`.`Data_status_id`)
INNER JOIN `qwer`.`client`
ON (`Data`.`Data_client_id` = `client`.`client_id`)
WHERE `Data_status`.`Data_status_name` IN ('PAID') AND MONTH(`Data_result`.`result_ts`) = MONTH(CURRENT_DATE())
AND YEAR(`Data_result`.`result_ts`) = YEAR(CURRENT_DATE())
GROUP BY `client`.`client_group`
Result of said query:
Table
Try to distinct before run the 'sum' check whether this solve your problem
SELECT `client_group` , FORMAT(SUM(`Data_result_amount` ),2) as sum from (
SELECT DISTINCT `client`.`client_group` , `Data_result`.`Data_result_amount`
FROM
`qwer`.`Data_result`
INNER JOIN `qwer`.`Data`
ON (`Data_result`.`Data_result_lead` = `Data`.`Data_id`)
INNER JOIN `qwer`.`Data_status`
ON (`Data_result`.`Data_result_status_id` = `Data_status`.`Data_status_id`)
INNER JOIN `qwer`.`client`
ON (`Data`.`Data_client_id` = `client`.`client_id`)
WHERE `Data_status`.`Data_status_name` IN ('PAID') AND MONTH(`Data_result`.`result_ts`) = MONTH(CURRENT_DATE())
AND YEAR(`Data_result`.`result_ts`) = YEAR(CURRENT_DATE())
) T
GROUP BY `client_group`
you can check the query here http://sqlfiddle.com/#!9/36a3f8/6
Here is my query:
SELECT DISTINCT `post_data`. * , pv.`seller_id` , pv.`islimited` , pv.`isquantity` , pv.`isslider`, `price`.`original_price` , `price`.`discount_percentage` , `timelimit`.`start_date` , `timelimit`.`expire_date` , `quantity`.`in_stock`, `currency`.`currency_symbol`, `seller`.`directory`, `post_to_cat`.`cat_id`, count(`sales`.`sales_id`) as sale FROM `post_view` AS pv
INNER JOIN `post_data` ON pv.`post_id` = `post_data`.`post_id` AND pv.`status` = 1
INNER JOIN `price` ON pv.`post_id` = `price`.`post_id`
INNER JOIN `currency` ON `price`.`currency_id` = `currency`.`currency_id`
INNER JOIN `seller` ON pv.`seller_id` = `seller`.`seller_id`
INNER JOIN `post_to_cat` ON `post_to_cat`.`cat_id` = 1 AND `post_to_cat`.`post_id` = `post_data`.`post_id`
LEFT JOIN `timelimit` ON ( CASE WHEN pv.`islimited` = 1 THEN `timelimit`.`post_id` ELSE -1 END ) = pv.`post_id`
LEFT JOIN `quantity` ON ( CASE WHEN pv.`isquantity` = 1 THEN `quantity`.`post_id` ELSE -1 END ) = pv.`post_id`
LEFT JOIN `sales` ON `sales`.`post_id` = pv.`post_id` AND `sales`.`status` = 1
WHERE pv.`status` = 1
ORDER BY pv.`post_id` DESC LIMIT 1
The ORDER BY DESC is not working, it just returns the first row from the table, but I want to get the highest post_id value row. What is the mistake I am making?
AS #Alex said in the comments you've got a LIMIT 1 at the end, you should probably bracket the last LEFT JOIN also for readability.
As #McAdam331 said we need data sample and sql fiddle to investigate what is wrong with you query. But at the moment I have some suggestions how to improve and debug your query.
First off all, what do I see the main and very left table in your query is post_view so all other tables should be LEFT JOIN if you want to get the max id. You should use INNER JOIN only if you think that other table could filter your main table somehow and order or result could be other table dependend. But in your case I see no reason to use INNER JOIN.
Second point is your very weird ON conditions:
LEFT JOIN `timelimit` ON ( CASE WHEN pv.`islimited` = 1 THEN `timelimit`.`post_id` ELSE -1 END ) = pv.`post_id`
LEFT JOIN `quantity` ON ( CASE WHEN pv.`isquantity` = 1 THEN `quantity`.`post_id` ELSE -1 END ) = pv.`post_id`
I have converted them into another one
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`start_date` ELSE NULL END as start_date ,
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`expire_date` ELSE NULL END as expire_date,
CASE WHEN pv.`isquantity`=1 THEN `quantity`.`in_stock` ELSE NULL END as in_stock,
But I still don't like it. It seems very useless to me. And has no sense when I read CASE WHEN pv.islimited=1 THEN timelimit.start_date ELSE NULL END as start_date so if flag pv.islimited=0 you don't need start_date? Are you sure?
And the last thing I can suggest: try to use my or even your query. But add every table by step while debugging. So First query just:
SELECT
pv.`post_id`, pv.`seller_id` , pv.`islimited` , pv.`isquantity` ,
pv.`isslider`
FROM `post_view` AS pv
WHERE pv.`status` = 1
ORDER BY pv.`post_id` DESC
LIMIT 1
If it returns correct post_id add next table:
SELECT
pv.`post_id`, pv.`seller_id` , pv.`islimited` , pv.`isquantity` ,
pv.`isslider`,
`post_data`. *
FROM `post_view` AS pv
LEFT JOIN `post_data`
ON pv.`post_id` = `post_data`.`post_id`
WHERE pv.`status` = 1
AND `post_data`.`slug` = 'abc'
ORDER BY pv.`post_id` DESC
LIMIT 1
Check the result. And continue step by step.
Yes it takes time. But that is debugging process. It could be the fastest way to get that query done. :-)
SELECT `post_data`. * ,
pv.`post_id`, pv.`seller_id` , pv.`islimited` , pv.`isquantity` ,
pv.`isslider`, `price`.`original_price` , `price`.`discount_percentage` ,
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`start_date` ELSE NULL END as start_date ,
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`expire_date` ELSE NULL END as expire_date,
CASE WHEN pv.`isquantity`=1 THEN `quantity`.`in_stock` ELSE NULL END as in_stock,
`currency`.`currency_symbol`, `seller`.`directory`, `post_to_cat`.`cat_id`, count(`sales`.`sales_id`) as sale
FROM `post_view` AS pv
LEFT JOIN `post_data`
ON pv.`post_id` = `post_data`.`post_id`
LEFT JOIN `price`
ON pv.`post_id` = `price`.`post_id`
LEFT JOIN `currency`
ON `price`.`currency_id` = `currency`.`currency_id`
LEFT JOIN `seller`
ON pv.`seller_id` = `seller`.`seller_id`
LEFT JOIN `post_to_cat`
ON `post_to_cat`.`cat_id` = 1
AND `post_to_cat`.`post_id` = pv.`post_id`
LEFT JOIN `timelimit`
ON `timelimit`.`post_id` = pv.`post_id`
LEFT JOIN `quantity`
ON quantity`.`post_id` = pv.`post_id`
LEFT JOIN `sales`
ON `sales`.`post_id` = pv.`post_id`
AND `sales`.`status` = 1
WHERE pv.`status` = 1
AND `post_data`.`slug` = 'abc'
GROUP BY pv.`post_id`
ORDER BY pv.`post_id` DESC
LIMIT 1
EDIT 1 - last GROUP BY pv.post_id was added as per #McAdam331 notice about count() function without GROUP BY
I believe the issue here is mostly as a result of preforming aggregation (using the COUNT()) function, without any group by. Although, it seems like you don't necessarily need it because you want that count only for the post in question.
If you're trying to gather all of that information for a single post, I would adjust your WHERE clause to have a condition to only gather that information for the post with the largest ID.
Instead of ordering by ID and limiting by 1, use a subquery to get the largest id, like this:
...
WHERE pv.status = 1 AND post_data.slug = 'abc' AND pv.post_id = (SELECT MAX(post_id) FROM post_view);
I wish to select results across several tables, but I only want to return rows based on the COUNT() result of joined SELECT query.
Here's how the query looks at the moment:
SELECT `s`.`venue_id` AS `id`,
CONCAT(`u`.`First_name`, ' ', `u`.`Surname`) AS `user_name`,
`u`.`avatar` AS `avatar`,
`u`.`facebookId` AS `fid`,
`x`.`imgs` AS `num_imgs`
FROM `new_shortlists_venues` `s`
INNER JOIN `new_shortlists` ON `new_shortlists`.`id` = `s`.`list_id`
INNER JOIN `users` `u` ON `u`.`id` = `new_shortlists`.`bride_id`
LEFT JOIN (SELECT `listing_id`, COUNT(*) `imgs` FROM `listingsImages`) `x` ON `s`.`venue_id` = `x`.`listing_id`
WHERE `new_shortlists`.`venues` > 4
AND `new_shortlists`.`bride_id` != 0
GROUP BY `s`.`list_id`
ORDER BY `s`.`date_added` DESC
LIMIT 6
For some reason, the query returns NULL for num_imgs. Essentially, I'd like to select only records which have at least 4 records in the listingsImages table.
Please note that this is for a legacy system, and I didn't design the DB! As a result, I have now option to change the schema.
You left off the GROUP BY of your subquery. Your current query is returning COUNT(*) associated with a random listing_id. Add GROUP BY listing_id and you should return the correct counts.
SELECT `s`.`venue_id` AS `id`,
CONCAT(`u`.`First_name`, ' ', `u`.`Surname`) AS `user_name`,
`u`.`avatar` AS `avatar`,
`u`.`facebookId` AS `fid`,
`x`.`imgs` AS `num_imgs`
FROM `new_shortlists_venues` `s`
INNER JOIN `new_shortlists` ON `new_shortlists`.`id` = `s`.`list_id`
INNER JOIN `users` `u` ON `u`.`id` = `new_shortlists`.`bride_id`
LEFT JOIN (SELECT `listing_id`, COUNT(*) `imgs`
FROM `listingsImages`
GROUP BY `listing_id`) `x` ON `s`.`venue_id` = `x`.`listing_id`
WHERE `new_shortlists`.`venues` > 4
AND `new_shortlists`.`bride_id` != 0
GROUP BY `s`.`list_id`
ORDER BY `s`.`date_added` DESC
LIMIT 6
And to return those with at least 4 records, just add that constraint to your WHERE criteria:
AND `x`.`imgs` >= 4
This might be the culprit:
ON `s`.`venue_id` = `x`.`listing_id`
How can I adjust this JOIN clause so that rows with a NULL value for the CountLocId or CountNatId columns are returned in the result?
In other words, if there is no match in the local_ads table, I still want the user's result from the nat_ads table to be returned -- and vice-versa.
SELECT u.franchise, CountLocId, TotalPrice, CountNatId, TotalNMoney, (
TotalPrice + TotalNMoney
)TotalRev
FROM users u
LEFT JOIN local_rev lr ON u.user_id = lr.user_id
LEFT JOIN (
SELECT lrr_id, COUNT( lad_id ) CountLocId, SUM( price ) TotalPrice
FROM local_ads
GROUP BY lrr_id
)la ON lr.lrr_id = la.lrr_id
LEFT JOIN nat_rev nr ON u.user_id = nr.user_id
INNER JOIN (
SELECT nrr_id, COUNT( nad_id ) CountNatId, SUM( tmoney ) TotalNMoney
FROM nat_ads
WHERE MONTH = 'April'
GROUP BY nrr_id
)na ON nr.nrr_id = na.nrr_id
WHERE lr.month = 'April'
AND franchise != 'Corporate'
ORDER BY franchise
Thanks in advance for your help!
try the following in where clause while making a left join. This will take all rows from right table with matched condition
eg.
LEFT JOIN local_rev lr ON (u.user_id = lr.user_id) or (u.user_id IS NULL)
Use this template, as it ensures that :
you have only one record per user_id (notice all subquerys have a GROUP BY user_id) so for one record on user table you have one (or none) record on subquery
independent joins (and calculated data) are not messed togeder
-
SELECT u.franchise, one.CountLocId, one.TotalPrice, two.CountNatId, two.TotalNMoney, (COALESCE(one.TotalPrice,0) + COALESCE(two.TotalNMoney,0)) TotalRev
FROM users u
LEFT JOIN (
SELECT x.user_id, sum(xORy.whatever) as TotalPrice, count(xORy.whatever) as CountLocId
FROM x -- where x is local_rev or local_ads I dont know
LEFT JOIN y on x.... = y.... -- where y is local_rev or local_ads I dont know
GROUP BY x.user_id
) as one on u.user_id = one.user_id
LEFT JOIN (
SELECT x.user_id, sum(xORy.whatever) as TotalNMoney, count(xORy.whatever) as CountNatId
FROM x -- where x is nat_rev or nat_ads I dont know
LEFT JOIN y on x.... = y.... -- where y is nat_rev or nat_ads I dont know
GROUP BY x.user_id
) as two on u.user_id = two.user_id
I am trying to bring back a string based on an IF statement but it is extremely slow.
It has something to do with the first subquery but I am unsure of how to rearrange this as to bring back the same results but faster.
Here is my SQL:
SELECT IF
(
(
SELECT COUNT(*)
FROM
(
SELECT DISTINCT enquiryId, type
FROM parts_enquiries, parts_service_types AS pst
WHERE parts_enquiries.serviceTypeId = pst.id
) AS parts
WHERE parts.enquiryId = enquiries.id
) > 1, 'Mixed',
(
SELECT DISTINCT type
FROM parts_enquiries, parts_service_types AS pst
WHERE parts_enquiries.serviceTypeId = pst.id AND enquiryId = enquiries.id
)
) AS partTypes
FROM enquiries,
entities
WHERE enquiries.entityId = entities.id
How can I make it faster?
I have modified my original query below, but I am getting the error that subquery returns more than one row:
SELECT
(SELECT
CASE WHEN COUNT(DISTINCT type) > 1 THEN 'Mixed' ELSE `type` END AS type
FROM parts_enquiries
INNER JOIN parts_service_types AS pst ON parts_enquiries.serviceTypeId = pst.id
INNER JOIN enquiries ON parts_enquiries.enquiryId = enquiries.id
INNER JOIN entities ON enquiries.entityId = entities.id
GROUP BY enquiryId) AS partTypes
FROM enquiries,
entities
WHERE enquiries.entityId = entities.id
Please have a look if this query yields the same results:
SELECT
enquiryId,
CASE WHEN COUNT(DISTINCT type) > 1 THEN 'Mixed' ELSE `type` END AS type
FROM parts_enquiries
INNER JOIN parts_service_types AS pst ON parts_enquiries.serviceTypeId = pst.id
INNER JOIN enquiries ON parts_enquiries.enquiryId = enquiries.id
INNER JOIN entities ON enquiries.entityId = entities.id
GROUP BY enquiryId
But N.B.'s comment is still valid. To see if and index is used and other information we need to see the EXPLAIN and the table definitions.
This should get you what you want.
I would first pre-query your parts enquiries and parts service types looking for both the count and MINIMUM of the part 'type', grouped by the enquiry ID.
then, run your IF() against that result. If the distinct count is > 0, then 'Mixed'. If only one, since I did the MIN(), it would only have the description of that one value that you desire anyhow.
SELECT
E.ID
IF ( PreQuery.DistTypes > 1, 'Mixed', PreQuery.FirstType ) as PartType
from
Enquiries E
JOIN ( SELECT
PE.EnquiryID,
COUNT( DISTINCT PE.ServiceTypeID ) as DistTypes,
MIN( PST.Type ) as FirstType
from
Parts_Enquiries PE
JOIN Parts_Service_Types PST
ON PE.ServiceTypeID = PST.ID
group by
PE.EnquiryID ) as PreQuery
ON E.ID = PreQuery.EnquiryID