I have a query, which will loop through an orders table, and as a sub query, will also count the number of rows in another table using a foreign key.
SELECT eo.*, (
SELECT COUNT(*)
FROM ecom_order_items eoi
WHERE eo.eo_id = eoi.eoi_parentid
AND eoi.site_id = '1'
) AS num_prods
FROM ecom_orders eo
WHERE eo.site_id = '1' AND eo_username = 'testuser'
Now, on the ecom_order_items table, it has a eoi_quantity field. I want the query to display the number of products for each order, taking into account the quantity field.
SELECT eo.*, (
SELECT COUNT(*) * eoi.eoi_quantity
FROM ecom_order_items eoi
WHERE eo.eo_id = eoi.eoi_parentid
AND eoi.site_id = '1'
) AS num_prods
FROM ecom_orders eo
WHERE eo.site_id = '1' AND eo_username = 'testuser'
However when I try this, it just gives me the same number as before. For the order I am testing on, it has 2 items, one with quantity 1, the other with quantity as 10, and num_prod is returning as 2 on both queries.
Any ideas? :)
If the value of eoi.eoi_quantity consists of multiple values, 1 and 10, only one of them will be selected and multiplied by COUNT(*). So you are getting the result 1 * 2.
As COUNT(*) = 2 for two items, do you want the result 2 * 1 + 2 * 10? It doesn't seem right to me. I'm thinking you want to count the total quantity over all the relevant orders, so why not use SUM(eoi.eoi_quantity) to get 1 + 10 instead? Thus you would have:
SELECT eo.*, (
SELECT SUM(eoi.eoi_quantity)
FROM ecom_order_items eoi
WHERE eo.eo_id = eoi.eoi_parentid AND eoi.site_id = '1'
) AS num_prods
FROM ecom_orders eo
WHERE eo.site_id = '1' AND eo_username = 'testuser';
But this is still going to get you the same value for each column. In fact, a subquery like (SELECT eo.*,...) will result in an error if it returns more than one row.
That's why Johan suggested that you would want to join the tables. You need to join the tables to be sure that the rows are properly linked and then group them by the id's you want for each row. How about:
SELECT eo.*, SUM(eoi.eoi_quantity)
FROM ecom_orders eo JOIN ecom_order_items eoi ON eo.eo_id = eoi.eoi_parentid
WHERE eo.site_id = '1'
AND eo_username = 'testuser'
GROUP BY eo.eo_id;
Rewrite the query into:
SELECT eo.*, sum(eoi.eoi_quantity) as sales
FROM ecom_orders eo
INNER JOIN ecom_order_items eoi ON (eo.eo_id = eoi.eoi_parentid)
WHERE eo.site_id = '1' AND eoi.site_id = '1' AND eo_username = 'testuser'
GROUP BY eo.eo_id;
Because the count(*) for each individual item is 1, count(*) * quantity is the same as sum(quantity).
Related
I am trying to create an advertisement query where I want to fetch data of all the impressions per advertisement. One user can have multiple advertisements and impressions will be counted in a table on per day basis. So for each day I will have one different row. Here is how my query currently looks like.
SELECT
eac.id,
eac.gender,
eac.start_date,
eac.end_date,
eac.ad_image_path,
eac.ad_link,
eac.requestfrom,
eac.traffic,
eac.registertype,
eacr.region_id,
eac.active,
eac.impression,
eac.center_image_path,
eac.bottom_image_path,
eac.approved_by,
er.name as country_name,
eac.budget,
sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp,
eaa.impression_count,
eac.customer_id,
eaa.created_at
FROM
`enrich_advert_customer` eac
JOIN `enrich_advert_customer_regions` eacr ON eac.id = eacr.advert_customer_id
JOIN `enrich_regions` er ON er.id = eacr.region_id
LEFT JOIN `enrich_advert_abstract` eaa on eac.id = eaa.advert_customer_id
WHERE
eac.requestfrom ='web' AND
eac.registertype = 'paid' AND
eac.active = 1 AND
eac.approved_by = 1 AND
eac.gender ='male' AND
er.name = 'india' AND
eac.start_date <= '2018-11-5' AND
eac.end_date >= '2018-11-10'
But the problem here is if I am using
sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp
this then its returning only one row at a time.
If you can suggest where I am making a mistake that will be helpful.
Thank you!
You need to add group by clause and others column in there as you applyied aggregation
SELECT eac.id,eac.gender,eac.start_date,eac.end_date,eac.ad_image_path,eac.ad_link,eac.requestfrom,eac.traffic,eac.registertype,eacr.region_id,eac.active,eac.impression,eac.center_image_path,eac.bottom_image_path,eac.approved_by,er.name as country_name,eac.budget,sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp ,eaa.impression_count,eac.customer_id,eaa.created_at
FROM
`enrich_advert_customer` eac
JOIN
`enrich_advert_customer_regions` eacr
ON eac.id = eacr.advert_customer_id
JOIN
`enrich_regions` er
ON er.id = eacr.region_id
LEFT JOIN
`enrich_advert_abstract` eaa
on eac.id = eaa.advert_customer_id
WHERE eac.requestfrom ='web' AND
eac.registertype = 'paid' AND
eac.active = 1 AND
eac.approved_by = 1 AND
eac.gender ='male' AND
er.name = 'india' AND
eac.start_date <= '2018-11-5' AND
eac.end_date >= '2018-11-10'
group by eac.id,eac.gender,eac.start_date,eac.end_date,eac.ad_image_path,eac.ad_link,eac.requestfrom,eac.traffic,eac.registertype,eacr.region_id,eac.active,eac.impression,eac.center_image_path,eac.bottom_image_path,eac.approved_by,er.name,eac.budget, eaa.impression_count,eac.customer_id,eaa.created_at
I want to include duplicates into my query. I havent succeeded in changing my "in" statements to "joins".
My expected result is a row count of 115.
My result is a row count of 108.
If i do a "Group by" in my first subquery, i get a row count of 108.
select match_id item_0, item_1, item_2, item_3, item_4, item_5, purchase_log
from player_matches where match_id IN
(select x.match_id from (select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id = 1 and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as x
inner join
(select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id
/*this is the statement that needs to be tweaked/changed */
IN (2,12,47,4,99) and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as y on y.match_id=x.match_id and x.team!=y.team)
and hero_id = 1
You can use the opendota inbrowser data-explorer to get a better understanding of my problem.
My subquery (returns 115)
My final Query (returns 108)
How do i get my final query to return 115 row counts?
My query is also really slow, is this because im using "in ()"?
It is because the IN will just check if the value is present. Use INNER JOIN instead:
select a.match_id, a.item_0, a.item_1, a.item_2, a.item_3, a.item_4, a.item_5, a.purchase_log
from player_matches a
INNER JOIN
(
select x.match_id from (select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id = 1 and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as x inner join (select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id in (2,12,47,4,5) and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as y on y.match_id=x.match_id and x.team!=y.team
) b ON a.match_id = b.match_id
WHERE hero_id = 1
Here's a demo from your original link.
I'm having trouble adding a condition on aliases is_paid, is_overdue and is_outstanding in the following query:
SELECT r.doc_number,
r.doc_date,
r.due_date,
r.currency,
r.amount,
r.vat,
r.vatammount,
(r.amount + r.vatammount) final_amount,
r.currency,
b.boq_id,
b.boq_comp_id,
b.boq_client_id,
b.boq_agency,
b.boq_date,
b.boq_orders,
b.receivable_id,
c.comp_name,
crm.`cn-name-first`,
crm.`cn-name-last`,
bi.inv_path,
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id) total_amount_received,
IF (r.amount + r.vatammount =
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id),
'1',
'0') AS is_paid,
IF (CURRENT_DATE >= r.due_date
AND r.amount + r.vatammount !=
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id),
'1',
'0') AS is_overdue,
IF (r.due_date < CURRENT_DATE
AND r.amount + r.vatammount !=
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id),
'1',
'0') AS is_outstanding
FROM receivables r
LEFT JOIN boq b ON b.receivable_id = r.id
LEFT JOIN boq_invoices bi ON bi.inv_boq_id = b.boq_id
LEFT JOIN comp_companies c ON c.comp_id = b.boq_comp_id
LEFT JOIN crm_contacts crm ON crm.contact_id = b.boq_client_id
WHERE r.status = 'active'
AND r.doc_type = 'inv'
AND b.boq_status = 'active'
AND is_paid = '1'
ORDER BY r.doc_date DESC LIMIT 10
Is there any way to modify this query and to make it possible to add a condition on those three aliases?
use alias in where condition .. is not allowed . because .is not possibile
the query code is evaluted based on a specified order .. starting from FROM then
WHERE clause and last the SELECT and the column alias so .. when the where is performed the column alias is not available at the query
You could try with an having condition because having work on the result of the query and not on the raw rows value .. (this could have effect on performance ..because all the query is performed and only the result is filtered by having)
I am trying to only get rows from video_index that belongs to a specific category from category_video_rel and order the result by COUNT of view count. This is the query I'm using:
SELECT
COUNT(DISTINCT view_count.id) AS count,
view_count.remove,
view_count.video_id,
video_index.id AS video_id,
video_index.active,
video_index.remove,
video_index.title AS title,
video_index.date_published AS date_published,
category_video_rel.active,
category_video_rel.remove,
category_video_rel.video_id AS cv_video_id,
category_video_rel.category_id AS category_id
FROM
view_count JOIN video_index
ON view_count.video_id = video_index.id,
category_video_rel JOIN video_index AS v
ON category_video_rel.video_id = v.id
WHERE
view_count.remove = '0' AND
video_index.active = '1' AND
video_index.remove = '0' AND
video_index.date_published <= '$current_time' AND
category_video_rel.category_id = '$category_id' AND
category_video_rel.active = '1' AND
category_video_rel.remove = '0'
GROUP BY
video_index.id
ORDER BY
count DESC
The problem is it outputs all the rows from video_index with a view count higher than 0 regardless of the category. Basically, it's ignoring "category_video_rel.category_id = '$category_id'" in the WHERE condition.
I have no idea what I'm doing wrong, please help.
Your FROM clause is mixing old style joins and new style joins
Instead try:
FROM
view_count JOIN video_index
ON view_count.video_id = video_index.id
JOIN category_video_rel
ON category_video_rel.video_id = video_index.id
I have table and this table contain result column with some entries. I just wanted to know how to get individual count these entries using MySql Query like this (see result required)...
also
(see the result column image and query) or helps are definitely appreciated
Result Column Image
Query
SELECT cpd.result FROM cron_players_data cpd
WHERE cpd.`status` = '1'
AND (cpd.`result` = '1' OR cpd.`result` = '2')
AND cpd.`player_id` = '81'
Result Required
result count
1 2
2 6
SELECT cpd.result, count(*) FROM cron_players_data cpd
WHERE cpd.`status` = '1'
AND (cpd.`result` = '1' OR cpd.`result` = '2')
AND cpd.`player_id` = '81' group by cpd.`result`
SELECT result, COUNT(result) `count` FROM
(
SELECT cpd.result result
FROM cron_players_data cpd
WHERE cpd.`status` = '1'
AND (cpd.`result` = '1' OR cpd.`result` = '2')
AND cpd.`player_id` = '81'
) a
GROUP BY result