select data from couple of subqueries in mysql - mysql

I have problem with mysql
I need to select sums from some joined tables but I dont get the result I need.
here's my query.
SELECT kelas.kelas as kelas, perpus.perpus as perpus
FROM
(SELECT b.id_alt, SUM(a.nilai_crips) AS kelas FROM crips AS a JOIN list AS b ON a.id_crips=b.id_crips where a.id_kriteria=34 group by b.id_alt
)as Kelas,
(SELECT SUM(a.nilai_crips) AS perpus FROM crips AS a JOIN list AS b ON a.id_crips=b.id_crips where a.id_kriteria=35 group by b.id_alt
)as perpus
group by kelas.id_alt
the 1st column shows the right result but the second column doesn't.
kelas | perpus
100 | 100
100 | 100
100 | 100
100 | 100
10 | 100
100 | 100
80 | 100
100 | 100
if I deleted the 1st subquery, the the column would return the right result.
perpus
100
100
100
100
100
100
100
76
what is wrong with my query? thank you in advance for the help.

Use a single SELECT, and conditionally add the values:
SELECT
b.id_alt,
SUM(IF(a.id_kriteria = 34,a.nilai_crips,0)) AS kelas,
SUM(IF(a.id_kriteria = 35,a.nilai_crips,0)) AS perpus
FROM crips AS a
JOIN list AS b
ON a.id_crips = b.id_crips
WHERE a.id_kriteria IN (34,35)
GROUP BY b.id_alt;

Related

SQL Problem regarding to get the sum of duplicate rows

This is my sql query to get the following table below :
select c.name, s.company, p.qty, p.qty * p.price as Total
from client c, purchase p, stock s
where c.clno = p.clno AND s.company = p.company
group by c.name, s.company, p.qty, p.qty * p.price
order by sum(p.qty) desc
The output of the above query looks like this :
Name | Company | Qty | Total
John ABC 12 100
Bob XYZ 10 150
John ABC 5 50
Bob XYZ 20 250
Bob XYZ 2 20
Nav QRS 10 150
John ABC 10 150
I want to have the query to get the output as the following :
Name | Company | Qty | Total
John ABC 27 300
Bob XYZ 32 420
Nav QRS 10 150
As of now your query uses GROUP BY but does not actually aggregates data. You want to GROUP BY name and company, and SUM the quantities and amounts, like :
select c.name, s.company, SUM(p.qty), SUM(p.qty * p.price) as Total
from client c
inner join purchase p on c.clno = p.clno
inner join stock s on s.company = p.company
group by c.name, s.company
order by Total desc
Other remarks regarding your query :
always use explicit joins instead of implicit ones
you can use column aliases in the ORDER BY clause (here, Total ; this can make the query easier to read

Join two tables using mysql

table:tab1
id date_time zoneid accountid slotid trequest bidder width height
_50832 2017-09-04 15:41:06 153 1654 153x468x60 10 aaa 468 60
_50832 2017-09-04 15:41:06 152 1654 152x468x60 10 bbb 468 60
table:tab2
id date_time zoneid accountid slotid bidder count
_50832 2017-09-04 15:41:06 152 1654 152x468x60 bbb 6
_50832 2017-09-04 15:41:06 152 1654 152x468x60 bbb 4
_50832 2017-09-04 15:41:06 153 1654 153x468x60 aaa 9
_50832 2017-09-04 15:41:06 153 1654 153x468x60 aaa 1
below is my query:
SELECT SUM(req.trequest) as REQ, SUM(win.count) as IMP
FROM tab1 as req
JOIN tab2 as win ON (req.id=win.id AND req.zoneid=win.zoneid)
GROUP BY req.zoneid
I get below result,
REQ IMP
20 10
20 10
IMP count is correct but I get wrong REQ count. My expected result is
REQ IMP
10 10
10 10
How to get my expected result?
Lets find the sum of trequest and count separately based on zoneid and id.Then use these two results ( t1 and t2 ) in the inner join.
Count mismatch problem shown in the question occur due to multiple rows satisfying the joining conditions.
In this solution we will only have one entry for each zoneid in both the results ( t1 and t2 ). So the problem is avoided.
Note: You can remove the id column from the GROUP BY clause if it doesn't make any difference.
SELECT t1.id, t1.zoneid, t1.REQ, t2.IMP FROM
(SELECT id,zoneid,SUM(trequest) as REQ
FROM tab1 GROUP BY zoneid,id ) t1
INNER JOIN
(SELECT id,zoneid SUM(win.count) as IMP
FROM tab2 GROUP BY zoneid,id ) t2
ON t1.id = t2.id
AND t1.zoneid = t2.zoneid
Let's try first sumwin.count and group records in sub-query, after it join tables. Try in following:
SELECT SUM(req.trequest) as REQ, SUM(win.count) as IMP
FROM tab1 as req
JOIN (
SELECT SUM(win.count) as IMP, win.zoneid, win.id
FROM tab2 as win
GROUP BY win.zoneid, win.id) AS win ON req.id=win.id AND req.zoneid=win.zoneid
GROUP BY req.zoneid
Instead of req.zoneid. You should try win.zoneid. What seems is that the rows in table 1 are counted multiple times as zoneid in table 2 comes twice. So win.zoneid would group it and avoid the repetition.
Updated: The solution posted by #mayur panchal is the correct one as you don't need to SUM the rows in first table as they belong to different zoneid. If you SUM them you will obviously get the 20 repeated twice.

Combine two separate SQL queries in a single query

I have these two tables:
Name | Income
----------|----------
Alice | 200
Bob | 100
Charlie | 50
Dave | 500
Name | Outcome
----------|----------
Alice | 300
Bob | 40
Charlie | 100
Dave | 250
I can make this query to get all the people who have an income which is greater than 150 and order them
SELECT Name, Income
FROM table1
WHERE Income > 150
ORDER BY Income DESC
Similarly I can get all the people who have an outcome which is less than 200:
SELECT Name, Outcome
FROM table2
WHERE Outcome < 200
ORDER BY Outcome DESC
Is there a way to get the two views by writing a single query i.e. using only one ;?
EDIT: I'm sorry, I just realised I wasn't clear about what I want to get. This is more or less what I am trying to achieve:
Name | Income
----------|----------
Dave | 500
Alice | 200
Name | Outcome
----------|----------
Charlie | 100
Bob | 40
I know about JOIN but that would make only one table in a result. I can't use UNION either because Outcome and Income do have same datatype but they mean different things.
What you are showing is still two separate results. One query gives you one result. If you want to combine the two queries that gives one query and one result. One method:
SELECT what, name, value
FROM
(
SELECT 'INCOME' as what, name, income as value, 1 as sortkey1, -income as sortkey2
FROM table1
WHERE income > 150
UNION ALL
SELECT 'OUTCOME' as what, name, outcome as value, 2 as sortkey1, outcome as sortkey2
FROM table2
WHERE outcome < 200
)
ORDER BY sortkey1, sortkey2;
You can JOIN these two tables by Name and SELECT both Income and Outcome, e.g.:
SELECT t1.name, t1.Income, t2.Outcome
FROM table1 t1 JOIN table2 t2 ON t1.Name = t2.Name
WHERE t1.Income > 150 AND t2.Outcome < 200
ORDER BY t1.Income DESC t2.Outcome DESC;
update (as per edits in question)
You can't have one query resulting on two separate outputs. Closest you can get to it is by using UNION with another column to distinguish between the outputs, e.g.:
SELECT Name, Income, 'Income'
FROM table1
WHERE Income > 150
ORDER BY Income DESC
UNION
SELECT Name, Outcome, 'Outcome'
FROM table2
WHERE Outcome < 200
ORDER BY Outcome DESC

mysql get last N records with MAX(date)

So I have following data in a product_rate_history table -
I want to select last N records ( eg 7 records ) informing rate change history of given product. If product rate is changed more than one time a day, then query should select most recent rate change for that day.
So from above table I want output like following for product id 16-
+-----------+-------------------------+------------------------+
| product_id | previous_rate | date |
+----------------+--------------------+------------------------|
| 16 | 2400 | 2016-04-30 23:05:35 |
| 16 | 4500 | 2016-04-29 11:02:42 |
+----------------+--------------------+------------------------+
I have tried following query but it returns only one row having last update rate only-
SELECT * FROM `product_rate_history` prh
INNER JOIN (SELECT max(created_on) as max FROM `product_rate_history` GROUP BY Date(created_on)) prh2
ON prh.created_on = prh2.max
WHERE prh.product_id = 16
GROUP BY DATE(prh.created_on)
ORDER BY prh.created_on DESC;
First, you do not need an aggregation in the outer query.
Second, you need to repeat the WHERE clause in the subquery (for the method you are using):
SELECT prh.*
FROM product_rate_history prh INNER JOIN
(SELECT max(created_on) as maxco
FROM product_rate_history
WHERE prh.product_id = 16
GROUP BY Date(created_on)
) prh2
ON prh.created_on = prh2.maxco
WHERE prh.product_id = 16
ORDER BY prh.created_on DESC;

Join derived table with itself

In short words:
I have events table:
[tbl]
time | newState
1200 | 1
1300 | 2
1400 | 5
I need to transform this table into intervals table [intervals]:
t0 | t1 | state
1200 | 1300 | 1
1300 | 1400 | 2
RESTRICTION: SQL COMPACT EDITION
the query:
SELECT leftPart.time AS t0, min(rightPart.time) AS t1, leftPart.newState
FROM tbl AS leftPart
LEFT OUTER JOIN tbl As rightPart
ON leftPart.time<rightPart.time
GROUP BY leftPart.Time,leftPart.newState
It works perfect when [tbl] is permanent table in database, but in my case [tbl] is derived from another select subquery! like this:
(SELECT time,newState
from ...) AS derivedTb
So, when i try something like this:
SELECT derivedTbl.time As t0,derivedTbl.state,min(rigthTblPart.time) FROM
(SELECT time,newState
from ...) AS derivedTbl
LEFT OUTER JOIN with derivedTbl AS rigthTblPart
ON derivedTbl.Time<rightTblPart.Time ...
It throws error: "derivedTbl does not exist"...
It seems that the derived table under it's alias is not visible to higher level query (thanks, google translator! ))...
Is there any way to store derived tables in query and using them in different parts of query? SQL CE doesn't support temporary tables, views and common table expressions...
task details (if interesting):
i have 2 tables of events:
[states1]
time | state1
1200 | 1
1300 | 2
1400 | 3
[states2]
time | state2
1200 | 0
1230 | 10
1330 | 20
1430 | 30
I need convert them in intervals table:
[intervals]
t0 t1 state1 state2
1200 1230 1 0
1230 1300 1 10
1300 1330 2 10
1330 1400 2 20
1400 1430 3 20
1430 NULL 3 30
stages of convertion:
1. overall timeline
(SELECT Time FROM States1
UNION
SELECT Time FROM States2) AS timetbl
join states1 table
join states2 table
for this moment all goes well:
SELECT states12tbl.time, states12tbl.state1, states2tbl.State AS state2
FROM (SELECT states12tbl_1.time, states12tbl_1.state1, MAX(states2tbl.Time) AS states2time
FROM (SELECT timetbl.time, states1tbl.State AS state1
FROM (SELECT timetbl_1.Time AS time, MAX(States1tbl.Time) AS state1time
FROM (SELECT Time
FROM States1
UNION
SELECT Time
FROM States2) AS timetbl_1 LEFT OUTER JOIN
States1 AS States1tbl ON States1tbl.Time <= timetbl_1.Time
GROUP BY timetbl_1.Time) AS timetbl INNER JOIN
States1 AS states1tbl ON timetbl.state1time = states1tbl.Time
join table with itself... and here is problem, i need to join code(3) with itself, because sql ce can't remember temp tables... If you have some better idea, please, share :)
Create a VIEW based on your first SELECT.
Onotole, I think that this WITH is making the trouble.
rewrite this query like
SELECT
derivedTbl.time As t0,
derivedTbl.state,
min(rigthTblPart.time)
FROM
(SELECT time,newState from ...) AS derivedTbl
LEFT OUTER JOIN derivedTbl AS rigthTblPart
ON derivedTbl.Time<rightTblPart.Time
....