How I can convert those colum to row? - sql

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

Solution to insert sub-query with additional group by

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;

Pivot and Sum of values in column based on specific row condition

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

How to turn repeated ranking(1-5) row data to column data in TSQL

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;

Need Help on Oracle Select Query

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;

How To Accumulator All The Values

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