Join derived table with itself - sql-server-2008

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
....

Related

Sum SQL Values Based On 20 Tables

I have 20 tables with same column with several example as below :
Australian GP
DRIVER | Points
================
HAM | 25
VET | 20
RIC | 15
Japanese GP
Driver | Points
==============
HAM | 25
VET | 20
RIC | 15
Malaysian GP
Driver | Points
RIC | 25
HAM | 20
VET | 15
I am planning to join all the 20 tables and all 20 driver datas as below for example :
Championship Standings
Driver | Points
HAM | 70
VET | 65
RIC | 50
Based on intense googling and massive confusion (I am bad at SQL since I have no spare time to learn outside my college), I have conclusion to use inner join and subquery such as below (which I don't know is it correct or a laughstock):
select driverid, point
from usa a, russia b, japan c
inner join (select driverid as Driver, sum(point) group by points);
I also thought that do I have to write 20 inner joins (as per example below) to connect the driver values between the tables?
(I created a table for Driver which contains driverid as primary key. All table that used to write points use foreign key from driver table)
Really really appreciate any helps regarding this case
You want union all`:
select driver, sum(points)
from ((select driver, points from usa) union all
(select driver, points from russia) union all
. . .
) c
group by driver;
Try this:
Select * From Table1
UNION ALL
Select * From Table2
UNION ALL
Select * From Table3
.
.
.
GROUP BY Driver
Where Table1, Table2, Table3 and so on are the names of your actual tables

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.

select data from couple of subqueries in 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;

one mysql query getting, per each row, the average of the previous three rows

i have something like this:
id | value
---------------
201311 | 10
201312 | 15
201401 | 20
201402 | 5
201403 | 17
and i need a result like this:
201311 | NULL or 0
201312 | 3.3 // 10/3
201401 | 8.3 // (15+10)/3
201402 | 15 // (20+15+10)/3
201403 | 13.3 // (5+20+15)/3
So far, i got to the point where i can get the AVG of the last three previous rows like this:
select AVG(c.value) FROM (select b.value from table as b where b.id < 201401 order by b.id DESC LIMIT 3) as c
passing the id manually. I'm not able to do it for each id.
Any ideas would be much appreciated!
thanks a lot.
regards
I think you'll have to write a stored procedure, use a cursor, iterate through the table and populate a new table using the values calculated in your cursor loop. If you need help with writing out the cursor loop, just drop a comment and I can get you an example.
i got to this now:
SELECT a.id, (select AVG(b.value) FROM table as b where b.id < a.id AND str_to_date(CONCAT(b.id,'01'), '%Y%m%d') >= DATE_SUB(str_to_date(CONCAT(a.id,'01'), '%Y%m%d'), INTERVAL 3 MONTH)) FROM `table` as a WHERE 1
But i'm quite sure there should be a better/cleaner solution
select a.id,coalesce(b.value,0) from test a left outer join
(select a.id, sum(b.value)/3 as value from
(select #row:=#row+1 as rownum,id,value from test,(select #row:=0)r) a,
(select #row1:=#row1+1 as rownum,id,value from test,(select #row1:=0)r) b
where b.rownum in (a.rownum-1,a.rownum-2,a.rownum-3)
group by a.rownum) b
on a.id=b.id;

MySQL Group by week num w/ multiple date column

I have a table with columns similar to below , but with about 30 date columns and 500+ records
id | forcast_date | actual_date
1 10/01/2013 12/01/2013
2 03/01/2013 06/01/2013
3 05/01/2013 05/01/2013
4 10/01/2013 09/01/2013
and what I need to do is get a query with output similar to
week_no | count_forcast | count_actual
1 4 6
2 5 7
3 2 1
etc
My query is
SELECT weekofyear(forcast_date) as week_num,
COUNT(forcast_date) AS count_forcast ,
COUNT(actual_date) AS count_actual
FROM
table
GROUP BY
week_num
but what I am getting is the forcast_date counts repeated in each column, i.e.
week_no | count_forcast | count_actual
1 4 4
2 5 5
3 2 2
Can any one please tell me the best way to formulate the query to get what I need??
Thanks
try:
SELECT weekofyear(forcast_date) AS week_forcast,
COUNT(forcast_date) AS count_forcast, t2.count_actual
FROM
t t1 LEFT JOIN (
SELECT weekofyear(actual_date) AS week_actual,
COUNT(forcast_date) AS count_actual
FROM t
GROUP BY weekOfYear(actual_date)
) AS t2 ON weekofyear(forcast_date)=week_actual
GROUP BY
weekofyear(forcast_date), t2.count_actual
sqlFiddle
You have to write about 30 (your date columns) left join, and the requirement is that your first date column shouldn'd have empty week (with a count of 0) or the joins will miss.
Try:
SELECT WeekInYear, ForecastCount, ActualCount
FROM ( SELECT A.WeekInYear, A.ForecastCount, B.ActualCount FROM (
SELECT weekofyear(forecast_date) as WeekInYear,
COUNT(forecast_date) as ForecastCount, 0 as ActualCount
FROM TableWeeks
GROUP BY weekofyear(forecast_date)
) A
INNER JOIN
( SELECT * FROM
(
SELECT weekofyear(forecast_date) as WeekInYear,
0 as ForecastCount, COUNT(actual_date) as ActualCount
FROM TableWeeks
GROUP BY weekofyear(actual_date)
) ActualTable ) B
ON A.WeekInYear = B.WeekInYear)
AllTable
GROUP BY WeekInYear;
Here's my Fiddle Demo
Just in case someone else comes along with the same question:
Instead of trying to use some amazing query, I ended up creating an array of date_columns_names and a loop in the program that was calling this query, and for each date_column_name, performing teh asme query. It is a bit slower, but it does work