SUM record with multiple join wrong - mysql

I have 3 table request, plan, level.
Here is table request:
id plan_id response_code client_id
1 1 200 1
2 1 200 1
3 1 400 1
4 1 500 1
Here is table plan:
id client_id
1 1
2 1
3 1
4 1
Here is table price:
id plan_id
1 1
2 2
3 3
4 4
I want join 3 table and count in table request, how many record with response_code 200, 400, and 500. But I get wrong value. Here is my query
SELECT
requests.id,
SELECT SUM(case
when requests.response_code = 200 then
1 else 0
end) as resquest200,
SELECT SUM(case
when requests.response_code = 500 then
1 else 0
end) as resquest500,
response_code,
FROM requests
JOIN plan
ON requests.plan_id = plan.id
JOIN price
ON plan.id = price.plan_id
GROUP BY request.id
I tried:
SELECT
request.id,
(
SELECT SUM(case
when request.response_code = 200 then
1 else 0
end) FROM request) as resquest200,
response_code,
FROM request
JOIN plan
ON requests.plan_id = plan.id
JOIN price
ON plan.id = price.plan_id
GROUP BY request.id
and it sum correctly. How can I optimize my query? Please help me

If you're looking to establishing the total number of requests then COUNT() is a better option than SUM()
SELECT COUNT(*), response_code FROM requests
GROUP BY response_code
Why do you want to join onto plan and price? Is there some data that from these tables that you need to return?

Related

How to achieve MySQL Query combining multiple COUNT() and GROUP BY

I have this data:
id date userid result
1 2015-05-01 1 a
2 2015-05-02 1 b
3 2015-05-03 1 b
4 2015-05-03 1 a
5 2015-05-04 1 a
I need to get users sorted by result:
id a b
1 1 1
2 1 1
You want conditional aggregation:
SELECT user_id, sum(result = 'win') AS wins, sum(result = 'loss') as losses
FROM table
GROUP BY user_id
ORDER BY wins DESC
LIMIT 4;
I would do it like this:
SELECT user_id,
SUM(CASE WHEN result='win' THEN 1 ELSE 0 END) AS wins,
SUM(CASE WHEN result='loss' THEN 1 ELSE 0 END) AS losses
FROM table1
GROUP BY user_id
ORDER BY wins DESC
LIMIT 4
Fiddle is here: http://sqlfiddle.com/#!9/00ac7/8

Mysql count rows of distinct values of price between range from give ids and return sum of count values

Hi I have two tables one is product and next is price table
Product Table
Id Name
1 Bike
2 Car
3 Van
Price Table
Id Price Pid
1 100 1
2 150 1
3 200 1
4 100 2
5 110 2
6 120 2
7 300 3
8 310 3
My Sql query
$sql = "SELECT SUM(CASE WHEN price >= 0 AND price <= 200 THEN 1 ELSE 0 END) AS `0-2`,
SUM(CASE WHEN price >= 201 AND price <= 500 THEN 1 ELSE 0 END) AS `2-5`,
COUNT(pid) AS `All Values`
FROM price where pid IN(1,2,3)";
when I run this query price count values showing like below
0-2 has (6) count
2-5 has (2) count
but here I need to display as like.
here I am looking to display as two products between 0-200 matched that are 1,2 pids and so on
0-2 (2) count
2-5 (1) count
because in price table there are more price options there for products so every product has 2 to 5 different prices in the table but I should display it as one product count even more prices had.
Kindly tell me how to write mysql query.
I would appreciate you help.
You can use COUNT(DISTINCT CASE ..) and in THEN clause use pid instead of 1
SELECT
COUNT(DISTINCT CASE WHEN price >= 0 AND price <= 200 THEN pid END) AS `0-2`,
COUNT(DISTINCT CASE WHEN price >= 201 AND price <= 500 THEN pid END) AS `2-5`,
COUNT(DISTINCT pid) AS `All Values`
FROM price
WHERE pid IN(1,2,3)
DEMO

SQL Query - How to get difference of sum of multiple of cells of rows

I need to get the difference of the sums of two fields which are in single table (really sorry if this is confusing), please read on for an example
Id type account_id stock_id volume price value
==========================================================
1 BUY 1 1 5 500 2500
2 BUY 1 4 30 200 6000
6 BUY 1 1 10 500 5000
7 SELL 1 1 3 500 1500
8 SELL 1 1 2 500 1000
9 SELL 1 4 20 120 2400
Above is my sample data and I would my SQL query result to be something like,
account_id stock_id volume totalAmount
============================================
1 1 10 5000
1 4 10 3600
basically here I am trying to get the total buy value of unique account & stock combination and subtract with the total sell value
Any help here would be highly appreciated.
Thanks in advance
Fiddle Test:
http://sqlfiddle.com/#!2/53035/1/0
select account_id,
stock_id,
sum(case when type = 'BUY' then volume else -volume end) as volume,
sum(case when type = 'BUY' then value else -value end) as totalamount
from tbl
group by account_id,
stock_id
having sum(case when type = 'BUY' then volume else -volume end) <> 0
I added the HAVING clause based on your comment.
Just to reduce duplication I would change Brian's code to this:
SELECT
account_id,
stock_id,
SUM(volume * type_sign) as total_volume,
SUM(value * type_sign) as total_value
FROM
(select t.*, case when type = 'BUY' then 1 else -1 end as type_sign
from tbl) t
GROUP BY account_id,
stock_id
select buy.account_id,buy.stock_id,(buy.volume-sell.volume) volume,(buy.totalAmount-sell.totalAmount) totalAmount from
(select account_id,stock_id,sum(volume) volume,sum(value) totalAmount from stock
where type = 'BUY'
group by account_id,stock_id) buy
inner join
(select account_id,stock_id,sum(volume) volume,sum(value) totalAmount from stock
where type = 'SELL'
group by account_id,stock_id) sell
on buy.account_id = sell.account_id and buy.stock_id = sell.stock_id

MySQL select using row counts and grouping

I have 2 tables, orders and order_lineitems.
orders contains the order status info (sold date, invoice no, type of sale, etc)
order_lineitems contains the item(s) for each order in a one to many relationship.
Since we provide shipping info by line item, ship_date is in the order_lineitems table, null if not shipped, a date if it is shipped.
I am trying to pull the orders where all items have shipped by comparing the number of line item rows against the line item rows that have a ship date. While I have successfully pulled all that info, I am unable to make the last step, limiting the result set to include only the completely shipped orders (number of rows = number of rows where ship_date is not null).
I know I am missing something simple, but just don't see it..
select sum(custom.lineitems) as totalitems, sum(custom.shipped) as totalshipped,
custom.invoice, z.shipregion
from (
select a.invoice, count(a.invoice) as lineitems, 0 as shipped
from order_lineitem a
group by a.invoice
UNION ALL
select b.invoice, 0 as notshipped, count(b.ship_date) as shipped
from order_lineitem b
where b.ship_date is not null
group by b.invoice
) as custom
left join orders z on custom.invoice = z.invoice
where z.result = 0
and z.respmsg like 'Approved%'
and z.shipregion <> 'PENDING'
and z.cancelorder = 0
group by custom.invoice;
This returns a result set like so (one row for each invoice in the DB)
totalitems totalshipped invoice shipregion
4 2 1000 REGION08
1 1 10001 REGION07
1 1 10004 REGION05
3 1 10006 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
What I am looking for is a result set like this - only where totalitems = totalshipped
totalitems totalshipped invoice shipregion
1 1 10001 REGION07
1 1 10004 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
Use HAVING clause
SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice HAVING lineitems = shipped
OR
SELECT a.invoice, a.shipregion, a.lineitems, a.shipped
FROM (SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice
) AS a WHERE a.lineitems = a.shipped
One more outer query needed.
select * from
(
\\Your whole query here
) as Result
where Result.totalitems = Result.totalshipped

Selecting a count on two separate conditions

Let's say I have the following data.
id name_id completed
1 10 1
2 10 0
3 15 1
4 10 0
5 20 1
6 15 0
7 20 1
8 15 0
I'm trying to find a count by the name id, which is pretty simple
SELECT name_id, COUNT(*) FROM db
GROUP BY name_id
Now, I have a second component which I want to include in the query.
For name_id 10, I want to count just those values where completed is 1. For the other name_id's, I want to select them regardless of whether they are 0 or 1.
So I should end up with:
name_id count(*)
10 1
15 3
20 2
Name_id 10 only has a count of 1 because it's just the 1 which is completed, while the other counts include both 0 and 1.
Can anyone help with this task.
Thanks!
You can use a CASE expression inside of your aggregate function.
SELECT name_id,
sum(case
when name_id = 10
then case when completed = 1 then 1 else 0 end
else 1 end) Total
FROM db
GROUP BY name_id;
See SQL Fiddle with Demo.
Exclude the rows where name_id = 10 and completed = 0:
SELECT name_id, COUNT(*) FROM db
WHERE NOT (completed = 0 AND name_id = 10)
GROUP BY name_id
SELECT name_id, COUNT(*) FROM db
WHERE name_id != 10 or completed = 1
GROUP BY name_id
Count when name_id is not 10. If it is 10, count when completed = 1:
SELECT
name_id,
COUNT(CASE WHEN name_id <> 10 or completed = 1 THEN 1 END)
FROM db
GROUP BY name_id