after convert, it should be
month 1 2 3 4 5 6 7 8 9 10 11 12
planqty 0 0 6230 0 0 0 0 0 0 0 0 0
actqty 0 0 2631 0 0 0 0 0 0 0 0 0
I will be so appreciated if you can help.
You want APPLY (i.e. CROSS APPLY) in order to convert columns to row wise.
select
qtynames as Month,
max(case when dt = '01' then qty end) [01],
max(case when dt = '02' then qty end) [02],
max(case when dt = '03' then qty end) [03],...
from table t cross apply (
values ('month', dt, 'planqty', planqty), ('month', dt, 'actqty', actqty)
)a(mnames, dates, qtynames, qty)
group by qtynames
Related
I'm trying to merge two working SQL query's in Oracle SQL Developer but can't seem to get the sub's Group By's to play nicely. I want/expect to see separate totals for each row but I'm getting an overall total for all rows.
I tried adding the second query as sub-query.
Query 1:
SELECT SOURCE,
sum(case when status = 'C1' then 1 else 0 end) as "C1",
sum(case when status = 'C2' then 1 else 0 end) as "C2",
sum(case when status = 'C3' then 1 else 0 end) as "C3",
sum(case when status = 'C4' then 1 else 0 end) as "C4",
sum(case when status = 'C5' then 1 else 0 end) as "C5"
FROM TABLE.req
GROUP BY SOURCE
ORDER BY SOURCE;
Query 2 to be added to the above:
SELECT SOURCE, COUNT(REQ.SOURCE) AS "Done in 7 Days"
FROM TABLE.req REQ
JOIN TABLE.audit AUD ON REQ.ROW_ID = AUD.RECORD_ID
WHERE (AUD.LAST_UPD - REQ.CREATED) <= 7
AND REQ.STATUS = 'Complete'
GROUP BY SOURCE;
Tried Sub-Query:
SELECT SOURCE,
sum(case when status = 'C1' then 1 else 0 end) as "C1",
sum(case when status = 'C2' then 1 else 0 end) as "C2",
sum(case when status = 'C3' then 1 else 0 end) as "C3",
sum(case when status = 'C4' then 1 else 0 end) as "C4",
sum(case when status = 'C5' then 1 else 0 end) as "C5"
(SELECT SOURCE, COUNT(REQ.SOURCE)
FROM TABLE.req REQ
JOIN TABLE.audit AUD ON REQ.ROW_ID = AUD.RECORD_ID
WHERE (AUD.LAST_UPD - REQ.CREATED) <= 7
AND REQ.STATUS = 'Complete'
GROUP BY SOURCE) AS "Done in 7"
FROM TABLE.req
GROUP BY SOURCE
ORDER BY SOURCE;
Query 1 returns:
A 0 0 0 0 0
B 0 0 3026 26 2461
C 0 0 0 0 0
D 3 39 2 1 19
E 0 0 61156 0 79430
Query 2 returns:
A 2906
B 10
C 28
D 7
E 0
ACTUAL:
Sub-Query returns the additional Column BUT it's being totaled
A 0 0 0 0 0 2951
B 0 0 3026 26 2461 2951
C 0 0 0 0 0 2951
D 3 39 2 1 19 2951
E 0 0 61156 0 79430 2951
EXPECTED:
Sub-Query returns the additional Column BUT it's being totaled
A 0 0 0 0 0 2906
B 0 0 3026 26 2461 10
C 0 0 0 0 0 28
D 3 39 2 1 19 7
E 0 0 61156 0 79430 0
You seem to want a correlated subquery:
SELECT SOURCE,
sum(case when status = 'C1' then 1 else 0 end) as "C1",
sum(case when status = 'C2' then 1 else 0 end) as "C2",
sum(case when status = 'C3' then 1 else 0 end) as "C3",
sum(case when status = 'C4' then 1 else 0 end) as "C4",
sum(case when status = 'C5' then 1 else 0 end) as "C5",
(SELECT COUNT(*)
FROM TABLE.req REQ r2 JOIN
TABLE.audit a
ON r2.ROW_ID = a.RECORD_ID
WHERE r2.SOURCE = r.SOURCE AND
(a.LAST_UPD - r2.CREATED) <= 7 AND
r2.STATUS = 'Complete'
)
FROM TABLE.req r
GROUP BY SOURCE
ORDER BY SOURCE;
I have a sample table like this:
DaysInOp Zone_id DailyAvg RunNumber
0 9 5996.79891226986 1
0 15 0 1
0 3 12549.5152623033 1
0 12 -8400.75508952542 1
0 6 24766.7738319152 1
0 7 11737.3698582701 1
0 1 26395.0374347879 1
0 18 0.0218623184855433 1
0 10 1965.53524850589 1
0 4 9499.54051554152 1
0 13 6158.45142253444 1
Where DaysinOp could be from 0-300
and Zone ID=1-20 and DailyAvg= Variable and RunNumber =1-5
I would like output like:
Day # Run 1 Weight (lbs) Run 2 Weight (lbs) Run 3 Weight (lbs) Run 4 Weight (lbs)
0 15 5 55 1
1 17 16 612 34
2 19 55 1100 56
3 22 100 1230 456
Etc. … … … …
Where Each run weight is Sum of daily avg values of Zone ID (1-10).
Please let me know if this is possible.
I am trying pivot with sum condition? Any hints will be appreciated.
SELECT
DaysInOp,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 1 THEN DailyAvg END) AS Run1Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 2 THEN DailyAvg END) AS Run2Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 3 THEN DailyAvg END) AS Run3Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 4 THEN DailyAvg END) AS Run4Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 5 THEN DailyAvg END) AS Run5Weight
FROM
yourTable
GROUP BY
DaysInOp
Can be simplified by moving the Zone_id BETWEEN 1 AND 10 to a WHERE clause. If a day has no records in those zones, however, it won't appear in the results.
SELECT
DaysInOp,
SUM(CASE WHEN RunNumber = 1 THEN DailyAvg END) AS Run1Weight,
SUM(CASE WHEN RunNumber = 2 THEN DailyAvg END) AS Run2Weight,
SUM(CASE WHEN RunNumber = 3 THEN DailyAvg END) AS Run3Weight,
SUM(CASE WHEN RunNumber = 4 THEN DailyAvg END) AS Run4Weight,
SUM(CASE WHEN RunNumber = 5 THEN DailyAvg END) AS Run5Weight
FROM
yourTable
WHERE
Zone_id BETWEEN 1 AND 10
GROUP BY
DaysInOp
#MatBailie provided the manual pivot, here's the same query using the pivot operator:
with t1 as (
select DaysInOp
, case when zone_id between 1 and 10 then dailyavg end rw
, RunNumber
from table1
)
select DaysInOp [Day #]
, [1] [Run 1 Weight (lbs)]
, [2] [Run 2 Weight (lbs)]
, [3] [Run 3 Weight (lbs)]
, [4] [Run 4 Weight (lbs)]
, [5] [Run 5 Weight (lbs)]
from t1
pivot (sum(rw)
for RunNumber in ([1],[2],[3],[4],[5])) pvt
I have a table data:
ID Sale Weekday
1 12 1
2 15 2
3 16 3
4 17 4
5 18 5
6 11 1
7 13 2
8 14 3
9 15 4
10 20 5
11 25 1
12 14 2
13 18 3
14 21 4
15 11 5
.. ..
I'd like to turn it into:
Mo Tu We Th Fr
12 15 16 17 18
11 13 14 15 20
25 14 18 21 11
..
Thank you!
Try this
SELECT SUM(case when Weekday = 1 then Sale else 0 end) as mn,
SUM(case when Weekday = 2 then Sale else 0 end) as Tu,
SUM(case when Weekday = 3 then Sale else 0 end) as We,
SUM(case when Weekday = 4 then Sale else 0 end) as Th,
SUM(case when Weekday = 5 then Sale else 0 end) as Fr
FROM
(
SELECT *,
Row_number()OVER(partition by weekday ORDER BY ID ) as seq_no
FROM tablename
) A
Group by seq_no
As mentioned in sample data if your table has all 5 days for all the week
SELECT SUM(case when Weekday = 1 then Sale else 0 end) as mn,
SUM(case when Weekday = 2 then Sale else 0 end) as Tu,
SUM(case when Weekday = 3 then Sale else 0 end) as We,
SUM(case when Weekday = 4 then Sale else 0 end) as Th,
SUM(case when Weekday = 5 then Sale else 0 end) as Fr
FROM
(
SELECT *,
( ( Row_number()OVER(ORDER BY ID ) - 1 ) / 5 ) + 1 seq_no
FROM tablename
) A
Group by seq_no
SQL FIDDLE DEMO
You could use the pivot operator together with a partitioned row_number like this:
select
max([1]) as 'Mo',
max([2]) as 'Tu',
max([3]) as 'We',
max([4]) as 'Th',
max([5]) as 'Fr'
from
(
select *, row_number() over (partition by weekday order by id) rn
from your_table
) a
pivot (max(sale) for weekday in ([1],[2],[3],[4],[5])) p
group by rn;
I am finding difficulty to frame a select query.
PFB, for the table and corresponding data:
ID DLS MATCH_STATUS LAST_UPDATE_TIME BO CH FT
1 0 0 09-07-2013 00:00:00 IT TE NA
1 1 1 09-07-2013 00:01:01 IT TE NA
2 0 0 09-07-2013 10:00:00 IP TE NA
3 0 0 09-07-2013 11:00:00 IT YT NA
3 2 2 09-07-2013 11:01:00 IT YT NA
Here
Match_Status 0-->Initial Record
1-->Singel Match
2-->Multi Match
For every record there will be a initial entry with match_status 0 and subsequent matching process end other number such as 1,2 will be update.
I am trying to retrieve records such as total record , waiting match ,single match and multi match group by BO, CH and FT
Below is the expected out put:
BO CH FT TOTAL_RECORD AWAITNG_MATCH SINGLE_MATCH MULTI_MATCH
IT TE NA 1 0 1 0
IP TE NA 1 1 0 0
IT YT NA 1 0 0 2
I have tried below query :
select BO,CH,FT,sum(case when match_status=0 then 1 else 0 end) as TOTAL_RECORD,
sum(case when match_status = 0 then 1 else 0 end) as AWAITING_MATCH,
sum(case when match_status = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when match_status = 2 then 1 else 0 end) as MULTI_MATCH from
table1 where last_update_time >= current_timestamp-1
group by BO,CH,FT;
problem with the above query is, awaiting_match is getting populated same as total record as I understand because of match_status=0
Similarly I tried with
select BO,CH,FT,sum(case when match_status=0 then 1 else 0 end) as TOTAL_RECORD,
select (sum(case when t1.ms=0 then 1 else 0 end) from
(select max(match_status) as ms from table1 where last_update_time >= current_timestamp-1 group by id)t1) )awaiting_match,
sum(case when match_status = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when match_status = 2 then 1 else 0 end) as MULTI_MATCH from
table1 where last_update_time >= current_timestamp-1
group by BO,CH,FT;
problem with the approach is awaiting_match is getting populated with the same value for subsequent row entry.
Please help me with a suitable query for the desired format.
Thanks a lot in advance.
It seems that you want the last match status. I am guessing that this is actually the maximum of the statuses. If so, the following solves the problem by first grouping on id and then doing the grouping to summarize:
select BO, CH, FT,
count(*) as TOTAL_RECORD,
sum(case when lastms = 0 then 1 else 0 end) as AWAITING_MATCH,
sum(case when lastms = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when lastms = 2 then 1 else 0 end) as MULTI_MATCH
from (select id, bo, ch, ft, MAX(match_status) as lastms
from table1
where last_update_time >= current_timestamp-1
group by id, bo, ch, ft
) t
group by BO, CH, FT;
If you actually want the last update to provide the status for the id, then you can use row_number() to enumerate the rows for each id, order by update time descending, and choose the first one:
select BO, CH, FT,
count(*) as TOTAL_RECORD,
sum(case when lastms = 0 then 1 else 0 end) as AWAITING_MATCH,
sum(case when lastms = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when lastms = 2 then 1 else 0 end) as MULTI_MATCH
from (select id, bo, ch, ft, match_status,
ROW_NUMBER() over (partition by id order by last_update_time desc) as seqnum
from table1
where last_update_time >= current_timestamp-1
) t
where seqnum = 1
group by BO, CH, FT;
the output i would like to display was accumulator of total EMPL_NUM. For example, the value show in the field TOTAL_FEBRUARY=TOTAL_JANUARY+TOTAL_FEBRUARY,while for the value exist in field TOTAL_MARCH=TOTAL_MARCH+TOTAL_JANUARY+TOTAL_FEBRUARY. I hope some of you can provide the solution for do it. Thank you very much. The coding is show as below:
SELECT
(CASE WHEN To_Char(A.EFFDT,'MM')=01 THEN 1
WHEN To_Char(A.EFFDT,'MM')=02 THEN 2
WHEN To_Char(A.EFFDT,'MM')=03 THEN 3
WHEN To_Char(A.EFFDT,'MM')=04 THEN 4
WHEN To_Char(A.EFFDT,'MM')=05 THEN 5
WHEN To_Char(A.EFFDT,'MM')=06 THEN 6
WHEN To_Char(A.EFFDT,'MM')=07 THEN 7
WHEN To_Char(A.EFFDT,'MM')=08 THEN 8
WHEN To_Char(A.EFFDT,'MM')=09 THEN 9
WHEN To_Char(A.EFFDT,'MM')=10 THEN 10
WHEN To_Char(A.EFFDT,'MM')=11 THEN 11
WHEN To_Char(A.EFFDT,'MM')=12 THEN 12
ELSE NULL END) AS MONTHS
,Count(*) AS EMPL_NUM
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=01 THEN 1 ELSE 0 END) AS TOTAL_JANUARY
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=02 THEN 1 ELSE 0 END) AS TOTAL_FEBRUARY
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=03 THEN 1 ELSE 0 END) AS TOTAL_MARCH
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=04 THEN 1 ELSE 0 END) AS TOTAL_APRIL
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=05 THEN 1 ELSE 0 END) AS TOTAL_MAY
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=06 THEN 1 ELSE 0 END) AS TOTAL_JUN
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=07 THEN 1 ELSE 0 END) AS TOTAL_JULY
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=08 THEN 1 ELSE 0 END) AS TOTAL_AUGUST
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=09 THEN 1 ELSE 0 END) AS TOTAL_SEPTEMBER
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=10 THEN 1 ELSE 0 END) AS TOTAL_OCTOBER
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=11 THEN 1 ELSE 0 END) AS TOTAL_NOVEMBER
,Sum(CASE WHEN To_Char(A.EFFDT,'MM')=12 THEN 1 ELSE 0 END) AS TOTAL_DECEMBER
FROM PS_JOB A
,PS_CITIZEN_PSSPRT B
,PS_CITIZENSHIP C
,PS_CITIZEN_STS_TBL D
WHERE A.HR_STATUS='A'
AND A.EFFDT=(SELECT Max(A1.EFFDT) FROM PS_JOB A1 WHERE A.EMPLID=A1.EMPLID AND A.EMPL_RCD=A1.EMPL_RCD AND A1.EFFDT<=SYSDATE)
AND A.EMPL_RCD=0
AND A.EFFSEQ=(SELECT Max(A2.EFFSEQ) FROM PS_JOB A2 WHERE A.EMPLID=A2.EMPLID AND A.EMPL_RCD=A2.EMPL_RCD AND A.EFFDT=A2.EFFDT)
AND A.EMPLID =B.EMPLID(+)
AND B.DEPENDENT_ID=' '
AND A.EMPLID=C.EMPLID
AND B.EMPLID=C.EMPLID
AND B.DEPENDENT_ID=C.DEPENDENT_ID
AND B.COUNTRY=C.COUNTRY
AND B.COUNTRY=D.COUNTRY
AND C.COUNTRY=D.COUNTRY
AND C.CITIZENSHIP_STATUS=D.CITIZENSHIP_STATUS
AND C.CITIZENSHIP_STATUS IN ('5','7')
AND To_Char(A.EFFDT,'YYYY')=2012
GROUP BY CASE WHEN To_Char(A.EFFDT,'MM')=01 THEN 1
WHEN To_Char(A.EFFDT,'MM')=02 THEN 2
WHEN To_Char(A.EFFDT,'MM')=03 THEN 3
WHEN To_Char(A.EFFDT,'MM')=04 THEN 4
WHEN To_Char(A.EFFDT,'MM')=05 THEN 5
WHEN To_Char(A.EFFDT,'MM')=06 THEN 6
WHEN To_Char(A.EFFDT,'MM')=07 THEN 7
WHEN To_Char(A.EFFDT,'MM')=08 THEN 8
WHEN To_Char(A.EFFDT,'MM')=09 THEN 9
WHEN To_Char(A.EFFDT,'MM')=10 THEN 10
WHEN To_Char(A.EFFDT,'MM')=11 THEN 11
WHEN To_Char(A.EFFDT,'MM')=12 THEN 12
ELSE NULL END
nter code here
Use <= operator when calculating SUM, e.g.:
Sum(CASE WHEN TO_NUMBER(To_Char(A.EFFDT,'MM')) <= 3 THEN 1 ELSE 0 END) AS TOTAL_MARCH
I think what you are asking for is a running total. Take a look at analytic functions (for example, the psoug site). If the core of your query is correct, do a regular aggregate in the inner query, then wrap that in an analytic function for the running total.
SELECT month
,SUM(month_count) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW )
AS running_total
FROM ( SELECT To_Char(A.EFFDT,'MM') AS month
,COUNT(*) AS month_count
FROM PS_JOB A
,PS_CITIZEN_PSSPRT B
,PS_CITIZENSHIP C
,PS_CITIZEN_STS_TBL D
WHERE A.HR_STATUS='A'
AND A.EFFDT=( SELECT Max(A1.EFFDT)
FROM PS_JOB A1
WHERE A.EMPLID=A1.EMPLID
AND A.EMPL_RCD=A1.EMPL_RCD
AND A1.EFFDT<=SYSDATE )
AND A.EMPL_RCD=0
AND A.EFFSEQ=( SELECT Max(A2.EFFSEQ)
FROM PS_JOB A2
WHERE A.EMPLID=A2.EMPLID
AND A.EMPL_RCD=A2.EMPL_RCD
AND A.EFFDT=A2.EFFDT )
AND A.EMPLID =B.EMPLID(+)
AND B.DEPENDENT_ID=' '
AND A.EMPLID=C.EMPLID
AND B.EMPLID=C.EMPLID
AND B.DEPENDENT_ID=C.DEPENDENT_ID
AND B.COUNTRY=C.COUNTRY
AND B.COUNTRY=D.COUNTRY
AND C.COUNTRY=D.COUNTRY
AND C.CITIZENSHIP_STATUS=D.CITIZENSHIP_STATUS
AND C.CITIZENSHIP_STATUS IN ('5','7')
AND To_Char(A.EFFDT,'YYYY')=2012
GROUP BY To_Char(A.EFFDT,'MM')
)
ORDER BY month