Noob question for nested query. Having a little issue with this SQL query. Please help. Trying to COUNT 2 fields in the same table and group by month, year. Query returns same results in new and renewal fields.
SELECT MONTH(p.created_at) as Month, YEAR(p.created_at) as Year,
(SELECT COUNT(p.id) FROM payments p
INNER JOIN carts c ON c.payment_id = p.id
INNER JOIN cart_items ci on ci.cart_id = c.id
WHERE ci.item_id = 8) as 'New',
(SELECT COUNT(p.id) FROM payments p
INNER JOIN carts c ON c.payment_id = p.id
INNER JOIN cart_items ci on ci.cart_id = c.id
WHERE ci.item_id = 13) as 'Renewal',
FROM payments p
GROUP BY month, year
Thanks for the help!
Query Expample
Month Year New Renewal
1 2010 1169 556
1 2011 1169 556
1 2012 1169 556
2 2010 1169 556
2 2011 1169 556
From looking at your query I'm guessing you have a items table which holds various possible purchasable items. Of which item_id = 8 corresponds to a "New" product and item_id = 13 corresponds to a "Renewal".
items are associated with the event of a prospective sale in a relation table called cart_items.
But not all carts are sold, but we only want to look at carts which are actually sold and so we're starting with the payments table.
Whether a prospective sale is paid for or not is recorded in the carts table by populating the payment_id.
A payment represents a cart that has been sold, we get the payments.id from payments, we take the payment_id to carts table and get the cart_id which we take to the cart_items table and get the actual items that were sold, and we want to count it separately if the item_id is 8 ('New') / 13 ('Renewal')
The query we're trying to run then is:
SELECT MONTH(p.created_at) as Month,
YEAR(p.create_at) as Year,
sum(if(ci.item_id = 8, 1, 0)) as New,
sum(if(ci.item_id = 13, 1, 0)) as Renewal
FROM payments p,
INNER JOIN carts c on c.payment_id = p.id
INNER JOIN cart_items ci on ci.cart_id = c.id
WHERE ci.item_id in (8,13)
GROUP BY month, year;
We get the entire data set, we group by the fields we want to group by and we total it up by counting the number of times we see item_id = 8 / item_id = 13.
I might have misunderstood the problem domain so please let me know if you need clarification or if I've gotten something wrong.
Related
I have three tables: product, sale and purchase.
I need to get the sum of sales and the sum of purchases of the products.
Even if no sales were made, I need it to show the purchases and vice-versa.
Something like:
Product | Sum of sales | Sum of purchases |
____________________________________________
product 1 | 10000 | 45000 |
product 2 | 20000 | 0 (or null) |
product 3 | 0(or null) | 20000 |
I've tried this, but it'll only return products that have both sales and purchases simultaneously:
select prod.name, sum(s.total), sum(p.total)
from product prod
inner join sale s on s.prod_id = prod.id
inner join purchase p on p.prod_id = prod.id
group by 1;
Thanks in advance.
Your query has a couple of issues. Firstly, because of the INNER JOIN it will (as you found) only return values for products which have both sales and purchases. This can be resolved by using LEFT JOIN (with an optional COALESCE to convert null values into 0). The second problem is that you will get duplicate rows from your JOIN where there is more than one sale or purchase of a product. To work around that, you need to perform the aggregation in derived tables for sales and purchases:
SELECT pr.name,
s.total AS sales, -- will show null if no sales
COALESCE(p.total, 0) AS purchases -- will show 0 if no purchases
FROM product pr
LEFT JOIN (SELECT prod_id, SUM(total) AS total
FROM sale
GROUP BY prod_id) s ON s.prod_id = pr.id
LEFT JOIN (SELECT prod_id, SUM(total) AS total
FROM purchase
GROUP BY prod_id) p ON p.prod_id = pr.id
I have two tables representing a database for customer products and its competitors' products:
tmp_match - from_product_id and to_product_id representing matches between customer product and competitor product respectively.
tmp_price_history - shows the price of each product per date.
I am trying to write a query which will list all dates from table tmp_price_history. For each date I want to see customer product price vs competitor product price according to product matches pairs in table tmp_match, regardless of whether there was a price history record for customer product or competitor product or both:
if both prices are available for a specific date - list them both in their columns
if there is only a record for customer product - show only customer price (and leave the competitor column blank).
if there is only record for competitor product - show competitor price in its column.
Expected result:
date from_product_id to_product_id cust_price comp_price
1 1 11 99 95
2 1 11 98 94
1 1 12 92
2 1 12 91
2 2 108
I tried to achieve that using this query:
select cust_hist.date, from_product_id, to_product_id, cust_hist.price as cust_price,comp_hist.price as comp_price
from tmp_match as matches
left join tmp_price_history cust_hist
on cust_hist.product_id = matches.from_product_id
left join tmp_price_history comp_hist
on comp_hist.product_id = matches.to_product_id
;
but it doesn't achieve my goal as can be seen in this sql snippet.
I think that you are looking for this:
select distinct *
from (SELECT date,
if(group_concat(distinct cust_price), from_product_id, null)as from_product_id,
if(group_concat(distinct comp_price), to_product_id, null) as to_product_id,
group_concat(distinct cust_price) as cust_price,
group_concat(distinct comp_price) as comp_price
FROM (select cust_hist.date,matches.from_product_id,
matches.to_product_id,cust_hist.price cust_price,
comp_hist.price comp_price
from tmp_match matches
inner join tmp_price_history cust_hist on matches.from_product_id = cust_hist.product_id
inner join tmp_price_history comp_hist on matches.to_product_id = comp_hist.product_id
WHERE comp_hist.date = cust_hist.date
union
select comp_hist.date,matches.from_product_id,
matches.to_product_id,null as cust_price,
comp_hist.price comp_price
from tmp_price_history comp_hist
join tmp_match matches
on matches.to_product_id = comp_hist.product_id # and matches.from_product_id is null
union
select cust_hist.date,matches.from_product_id,
matches.to_product_id,
cust_hist.price cust_price,
null comp_price
from tmp_price_history cust_hist
join tmp_match matches
on matches.from_product_id = cust_hist.product_id # and matches.to_product_id is null
order by DATE, from_product_id, to_product_id, cust_price, comp_price) as u
group by date,from_product_id,to_product_id) g
Your idea about sql snippet was great!
I have 3 tables :
I need to retrieve the name of the sellers that have sold during January AT LEAST one product where the total amount of sales of this said product during January is greater than 1000.
I thought about starting like this :
SELECT c.nom, c.prenom
FROM Commerciaux c
LEFT JOIN Ventes v ON c.id_commerciaux = v.id_commerciaux
WHERE EXISTS (SELECT 1
FROM Produits p, Ventes v
WHERE p.id_produits = v.id_produits
AND MONTH(v.date) = 1
GROUP BY p.nom
HAVING SUM(v.montant) > 200)
AND MONTH(v.date) = 1
GROUP BY c.nom, c.prenom
The SELECT in the WHERE EXISTS seems to be working, but when I have to get link the table Sellers, I don't know how to write it.
Any help would be great !
You can use something like this:
select distinct s.name
from Sellers s,
( -- get all those products that qualify (more than 1000 sales)
select product_id, sum(amount) as total
from Sales
where Month(date) = 1
group by product_id
having total > 1000
) vp,
Sales sa
where
s.id = sa.commercial_id and
sa.product_id = vp.id and
Month(sa.date) = 1
#Leo answer would return only those Sellers that have sold more than 100 of the product in January instead of returning all Sellers that have sold any amount of the product that has been sold in an amount greater than 1000 across the board.
You could use a nested query:
SELECT s.name FROM
(Sellers as s JOIN Sales as sp on sp.commercial_id = s.id) JOIN
Product as p on p.id = sp.product_id
WHERE MONTH(sp.date) = 1 AND YEAR(sp.date) = 2017 AND
(SELECT SUM(Amount) FROM Sales as sp2 WHERE sp2.commercial_id = s.id
AND sp2.product_id = p.id
AND MONTH(sp2.date) = 1 AND YEAR(sp2.date) = 2017) > 1000
First, join the three tables on foreign keys, and then run a nested query to compute amount of the selected seller on a specific product to check to pass the amount limitation.
try this
SELECT C.name
FROM Sales A
JOIN Product B ON A.produit_id = B.id
JOIN Seller C ON A.commercial_id = C.id
WHERE MONTH(A.date) = 1
HAVING SUM(A.nAmount) > 100
GROUP BY C.name
I am stuck with the following requirement and I am finding it difficult to crack the query for it.
Consider a table customer with the following fields
id signup_date first_payment_date
10 2015-03-20 null
11 2015-03-20 null
12 2015-03-20 null
13 2015-03-20 null
14 2015-05-23 null
15 2015-05-23 null
Consider another table transaction_history
id product_name
10 vod trial
10 vod trial
11 vod trial
12 vod trial
12 vod
13 vod trial
14 vod trial
15 vod trial
15 vod trial
I need to pick the idfrom customer table and look up in transaction_history table based on the signup_date and first_payment_date is null.
Now I need to check if this id is present in transaction_history and check if he has at least 1 entry with product_name = "vod trial". If he has then he is a row in the result I want.
At the end I need to calculate the total number of id's from transaction_history who has at least one row where product_name="vod_trial" and this should be on a date basis mentioned in signup_date in customer table.
I wrote a query in the following manner:
SELECT
ts.guid,
cs.signup_date,
(SELECT
COUNT(ts2.guid)
FROM
transaction_history ts2
WHERE
cs.guid = ts2.guid
AND ts2.product_name = "vod trial"
HAVING COUNT(ts2.guid) = 1) AS count_ts_guid
FROM
customer AS cs,
transaction_history AS ts
WHERE
cs.guid = ts.guid
AND cs.first_payment_date IS NULL;
But in the above query I am not able to calculate the total count signup_datewise.
Would be great if someone could help me out.
Sample result:
date new trials
2015-03-20 2
2015-05-23 1
I am not sure I fully understand. You want customers without first_payment_date that have a trial entry in the transaction table?
select *
from customer
where first_payment_date is null
and id in (select id from transaction_history where product_name = 'vod trial');
Okay, from your last comment it seems, you want customers that have no trial entry in the transaction table, too. And you want to display them with their trial transaction count. So:
select signup_date,
(
select count(*)
from transaction_history th
where th.product_name = 'vod trial'
and th.id = c.id
)
from customer c
where first_payment_date is null;
If you even want to group by date, then aggregate:
select signup_date,
sum((
select count(*)
from transaction_history th
where th.product_name = 'vod trial'
and th.id = c.id
))
from customer c
where first_payment_date is null
group by signup_date;
Next try: Join all customers and transactions, such as to only get customers present in the transactions table. Then aggregate.
select c.signup_date, count(*)
from customer c
join transaction_history th on th.id = c.id and th.product_name = 'vod trial'
where c.first_payment_date is null
group by c.signup_date;
Or do you want this:
select c.signup_date, count(case when th.product_name = 'vod trial' then 1 end)
from customer c
join transaction_history th on th.id = c.id
where c.first_payment_date is null
group by c.signup_date;
I'd better make this a separate answer. You want to find customers that have only one entry in transaction_history and that entry must be 'vod trial'. So read the transaction table, group by customer id and count. Check your criteria with HAVING. Then join the found IDs with the customer table and group by date.
select c.signup_date, count(*)
from customer c
join
(
select id
from transaction_history
group by id
having count(*) = 1
and min(product_name) = 'vod trial'
) t on t.id = c.id
group by c.signup_date;
I am trying to make one query, to get some statistic data from database.
My tables structure described here:
PRODUCTS
id | price | buy_price | vendor_code | ...
ORDERS
id | shipping_method_id | ...
ORDER_ITEMS
id | order_id | product_id | quantity | ...
SHIPPING_METHODS
id | cost | ...
SUPPLIERS
id | code | ...
I want to get data like this. In words, I am making reports on Product total income, expenses and quantity of buys in my ecommerce, and want them to group by supplier. I wrote this sql:
SELECT orders.id,
suppliers.code,
COUNT(products.id)*items.quantity buys,
SUM(products.price*items.quantity + shipping_methods.cost) sales,
SUM(products.buy_price*items.quantity) expenses
FROM `orders` orders
INNER JOIN `order_items` items ON items.order_id = orders.id
INNER JOIN `products` products ON items.product_id = products.id
INNER JOIN (SELECT DISTINCT suppliers.code FROM `suppliers`) suppliers
ON products.vendor_code LIKE CONCAT(suppliers.code, '%%')
INNER JOIN `shipping_methods` shipping_methods ON orders.shipping_method_id = shipping_methods.id
WHERE (
orders.delivery_date_to BETWEEN '2011-11-18' AND '2011-11-19'
)
GROUP BY suppliers.code, orders.id
ORDER BY buys DESC
this returns to me this data:
order_id code buys sales expenses
85 SB 4 1504 1111.32
84 VD 2 496 350.82
60 lg 2 1418 1052.31
88 SB 1 376 277.83
When I change GROUP BY suppliers.code, orders.id to GROUP BY suppliers.code, it returns almost correct data, I mean data is grouped by code, but counting is wrong. Admit that sales and expenses are correct
order_id code buys sales expenses
85 SB 8 1880 1389.15
60 lg 2 1418 1052.31
84 VD 2 496 350.82
If u see SB counted total 8 sales, but really there are only 5, as u can see in previous table. I'm sure I missed something in my query, but cant understand how to correct this.
PS field order_id are unused in my further scripts, I use it because django's Model.objects.raw() query does need to have primary key in result, don't really understand why
try this query.
SELECT t1.code, SUM(t1.buys), SUM(t1.sales) FROM (
SELECT orders.id,
suppliers.code,
COUNT(products.id)*items.quantity buys,
SUM(products.price*items.quantity + shipping_methods.cost) sales,
SUM(products.buy_price*items.quantity) expenses
FROM `orders` orders
INNER JOIN `order_items` items ON items.order_id = orders.id
INNER JOIN `products` products ON items.product_id = products.id
INNER JOIN (SELECT DISTINCT suppliers.code FROM `suppliers`) suppliers
ON products.vendor_code LIKE CONCAT(suppliers.code, '%%')
INNER JOIN `shipping_methods` shipping_methods ON orders.shipping_method_id = shipping_methods.id
WHERE (
orders.delivery_date_to BETWEEN '2011-11-18' AND '2011-11-19'
)
GROUP BY suppliers.code, orders.id
ORDER BY buys DESC
) AS t1
GROUP BY t1.code
Edit: I've forgotten SUM() parts. Just added, please retry if you've already tried.