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
Related
I am trying to generate a report, and so far have one completed that gives me how many orders, for each day, are in status 1-9.
TableA structure looks like this:
Sales Order | Order Status | Order Date
123456789 | 1 | 2017-02-22 00:00:00.000
123456790 | 0 | 2017-02-21 00:00:00.000
TableB structure looks like this:
Sales Order | Price
123456789 | 123.00
123456789 | 42.00
123456790 | 56.00
123456790 | 28.00
This code:
SELECT
MAX(year([OrderDate])) as Yr,
MAX(MONTH([OrderDate])) as M,
Day([OrderDate]) as Day,
sum(case when [OrderStatus]='0' THEN 1 ELSE 0 END) AS 'STATUS"0"',
sum(case when [OrderStatus]='1' THEN 1 ELSE 0 END) AS 'STATUS"1"',
sum(case when [OrderStatus]='2' THEN 1 ELSE 0 END) AS 'STATUS"2"',
sum(case when [OrderStatus]='4' THEN 1 ELSE 0 END) AS 'STATUS"4"',
sum(case when [OrderStatus]='8' THEN 1 ELSE 0 END) AS 'STATUS"8"',
sum(case when [OrderStatus]='9' THEN 1 ELSE 0 END) AS 'STATUS"9"',
sum(case when [OrderStatus]='S' THEN 1 ELSE 0 END) AS 'STATUS"S"',
sum(case when [OrderStatus]='*' THEN 1 ELSE 0 END) AS 'STATUS"*"',
sum(case when [OrderStatus]='/' THEN 1 ELSE 0 END) AS 'STATUS"/"'
FROM
SorMaster
WHERE
YEAR([OrderDate]) = YEAR(GETDATE())
GROUP BY
DATENAME(month, DateAdd(month, Month([OrderDate]) - 1, Cast('2008-01-01' AS Datetime))), Day([OrderDate])
ORDER BY
Yr DESC, M DESC, Day DESC
Returns this:
Yr | M | Day | STATUS"0" | STATUS"1" | STATUS"2" | STATUS"4" | STATUS"8" | STATUS"9" | STATUS"S" | STATUS"*" | STATUS"/"
2017 2 22 0 2 0 1 0 0 5 0 0
2017 2 21 0 0 0 7 0 0 0 0 0
This is PERFECT for my first report.
Now, comes the trouble. My Problem is that I need to nest-query Table B, so that instead of returning a count(orders), I need the sum(orders) those totals for each order are in Table B.
Using the above example, the query would need to return something like this:
Yr | M | Day | STATUS"0" | STATUS"1" | STATUS"2" | STATUS"4" | STATUS"8" | STATUS"9" | STATUS"S" | STATUS"*" | STATUS"/"
2017 2 22 0 165 0 0 0 0 0 0 0
2017 2 21 84 0 0 0 0 0 0 0 0
Any pointers?
Just join to TableB:
SELECT MAX(year([t1.OrderDate])) AS Yr,
MAX(MONTH([t2.OrderDate])) AS M,
DAY([t1.OrderDate]) AS Day,
SUM(CASE WHEN [OrderStatus] = '0' THEN t2.Price ELSE 0 END) AS 'STATUS"0"',
SUM(CASE WHEN [OrderStatus] = '1' THEN t2.Price ELSE 0 END) AS 'STATUS"1"',
SUM(CASE WHEN [OrderStatus] = '2' THEN t2.Price ELSE 0 END) AS 'STATUS"2"',
SUM(CASE WHEN [OrderStatus] = '4' THEN t2.Price ELSE 0 END) AS 'STATUS"4"',
SUM(CASE WHEN [OrderStatus] = '8' THEN t2.Price ELSE 0 END) AS 'STATUS"8"',
SUM(CASE WHEN [OrderStatus] = '9' THEN t2.Price ELSE 0 END) AS 'STATUS"9"',
SUM(CASE WHEN [OrderStatus] = 'S' THEN t2.Price ELSE 0 END) AS 'STATUS"S"',
SUM(CASE WHEN [OrderStatus] = '*' THEN t2.Price ELSE 0 END) AS 'STATUS"*"',
SUM(CASE WHEN [OrderStatus] = '/' THEN t2.Price ELSE 0 END) AS 'STATUS"/"'
FROM SorMaster t1
LEFT JOIN TableB t2
ON t1.[Sales Order] = t2.[Sales Order]
WHERE YEAR([OrderDate]) = YEAR(GETDATE())
GROUP BY DATENAME(month,DateAdd(month,Month([OrderDate])-1,Cast('2008-01-01' AS Datetime))),
DAY([OrderDate])
ORDER BY Yr DESC, M DEACLLSC, Day DESC
That's not too difficult, just a matter of LEFT JOINing in table B and then summing the prices in that. There's a couple of small tricks here. You want to LEFT JOIN to ensure that rows in table A always show up, even if there are no corresponding rows in table B. Secondly, in your SUM() statement, you'll need to add a COALESCE(...,0.00) to ensure you're summing decimals and no NULL values creep in from the LEFT JOIN. Oddly in databases, NULL + {anything} = NULL.
For the below query, you'll need to change the name of TableB to whatever the table name is, and the JOIN predicate will need to have the column names named accurately, and delimited correctly if they contain spaces. For example, in MSSQL the delimiters are [ and ], e.g. MyTable.[My Column With Spaces]
SELECT
MAX(YEAR([OrderDate])) as Yr,
MAX(MONTH([OrderDate])) as M,
DAY([OrderDate]) as Day,
sum(case when [OrderStatus]='0' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"0"',
sum(case when [OrderStatus]='1' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"1"',
sum(case when [OrderStatus]='2' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"2"',
sum(case when [OrderStatus]='4' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"4"',
sum(case when [OrderStatus]='8' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"8"',
sum(case when [OrderStatus]='9' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"9"',
sum(case when [OrderStatus]='S' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"S"',
sum(case when [OrderStatus]='*' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"*"',
sum(case when [OrderStatus]='/' THEN COALESCE(TableB.Price, 0.00) ELSE 0.00 END) AS 'STATUS"/"'
FROM SorMaster
LEFT OUTER JOIN TableB
ON TableB.SalesOrder = SorMaster.SalesOrder
WHERE YEAR([OrderDate]) = YEAR(GETDATE())
GROUP BY
DATENAME(month,DateAdd(month,Month([OrderDate])-1,Cast('2008-01-01' AS Datetime))),
DAY([OrderDate])
ORDER BY
Yr DESC,
M DESC,
Day DESC
By (left) joining tableB and replacing your 'count' ones by tableB.price you should get the sum of all positions of orders with the according status.
I have this query :
SELECT WorkId, RegisterDate, sum(RoomType1) As RoomType1, sum(RoomType2) As RoomType2, sum(RoomType3) As RoomType3, sum(RoomType4) As RoomType4, sum(RoomType5) As RoomType5, sum(RoomType6) As RoomType6, sum(RoomType7) As RoomType7, sum(RoomType8) As RoomType8
FROM (
SELECT dbo.[Work].WorkId, dbo.[Work].RegisterDate,
case dbo.Floor.RoomType when 1 then 1 else 0 end as RoomType1,
case dbo.Kat.RoomType when 2 then 1 else 0 end as RoomType2,
FROM dbo.Belediye INNER JOIN
dbo.[Is] ON dbo.Municipality.MunicipalityId= dbo.[Is].MunicipalityWorkId INNER JOIN
dbo.Look ON dbo.[Work].LookWorkId = dbo.Look.LookId ,
WHERE (dbo.Look.LocationIS NOT NULL)
) E
GROUP BY WorkId,
This query works as expected, but I can't understand why it has two selects, why does it need them? Please explain it to me. Thanks.
As you suspected this query dont need two selects and could be rewritten without sub-query:
SELECT i.IsId,
i.KayitTarihi,
SUM(case k.OdaTipi when 1 then 1 else 0 end) as RoomType1,
SUM(case k.OdaTipi when 2 then 1 else 0 end) as RoomType2,
SUM(case k.OdaTipi when 3 then 1 else 0 end) as RoomType3,
SUM(case k.OdaTipi when 4 then 1 else 0 end) as RoomType4,
SUM(case k.OdaTipi when 5 then 1 else 0 end) as RoomType5,
SUM(case k.OdaTipi when 6 then 1 else 0 end) as RoomType6,
SUM(case k.OdaTipi when 7 then 1 else 0 end) as RoomType7,
SUM(case k.OdaTipi when 8 then 1 else 0 end) as RoomType8
FROM dbo.Belediye b
INNER JOIN dbo.[Is] i
ON b.BelediyeId = i.BelediyeIsId
INNER JOIN dbo.YerGorme yg
ON i.YerGormeIsId = yg.YerGormeId
INNER JOIN dbo.Kat k
ON yg.YerGormeId = k.YerGorme_YerGormeId
WHERE yg.Lokasyon IS NOT NULL
GROUP BY i.IsId, i.KayitTarihi
Note: use table aliases
I need to count combinations of products within transactions differently to other products and I'm struggling with how to do this within a single select statement from SQL 2008. This would then become a data set to manipulate in Reporting Services
raw data looks like this
txn, prod, units
1, a, 2
1, c, 1
2, a, 1
2, b, 1
2, c, 1
3, a, 2
3, b, 1
4, a, 3
4, c, 2
So a+b should = one if in same trans number, however a or b should equal one if not paired. So a=1 and b=1 but a+b=1, a+b+a=2, a+b+a+b=2 given the example data here is my desired result with an explanation of why
txn 1 is 3 units -- 2a + c
txn 2 is 2 units -- (a+b) + c
txn 3 is 2 units -- (a+b) + a
txn 4 is 5 units -- 3a + 2c
My query is more complex than this and includes other aggregates so I would like to group by transaction which I can't do as I need to manipulate at a lower grain
Update Progress :
Possible solution, I've generated columns based on the products I'm measuring. This allows me to group on Txn as I am now aggregating that field. Unsure if there's a better way to do it as it does take a little while
CASE WHEN SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end)=0
THEN SUM(CASE WHEN Prod='a' then 1 else 0 end)
ELSE 0 END AS MixProd
, CASE WHEN SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end)!=0
THEN ABS(SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end))
ELSE 0 END AS NotMixProd
I will then need to sort out the current unit aggregate to remove the extras but this certainly gives me a start
Update Progress 2 :
This failed to handle 0 correctly where a or b was 0 it would still give a value for mix because a-b was not zero. I reverted to an earlier draft that I lost and expanded as per below
, CASE WHEN SUM(CASE WHEN Prod='a' then 1 else 0 end) = 0 THEN 0
WHEN SUM(CASE WHEN Prod='b' then 1 else 0 end) = 0 THEN 0
WHEN SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end)=0
THEN SUM(CASE WHEN Prod='a' then 1 else 0 end)
ELSE ABS(SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end))
END AS MixProd
, CASE WHEN SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end)!=0
THEN ABS(SUM(CASE WHEN Prod='a' then 1 else 0 end)-
SUM(CASE WHEN Prod='b' then 1 else 0 end))
ELSE 0 END AS NotMixProd
UPDATE: This should work in SQL Server 2008 (based on LAG solution from here).
Here is the demo: http://rextester.com/GNI23706
WITH CTE AS
(
select txn, prod, units,
row_number() over (partition by txn order by prod) rn,
(row_number() over (partition by txn order by prod))/2 rndiv2,
(row_number() over (partition by txn order by prod)+1)/2 rnplus1div2,
count(*) over (partition by txn) partitioncount
from test_data
)
select
txn,
sum(case when prev_prod = 'a' and prod = 'b' and prev_units >= units then 0
when prev_prod = 'a' and prod = 'b' and prev_units < units then units - prev_units
else units
end) units
from
(
select
txn,
prod,
units,
CASE WHEN rn%2=1
THEN MAX(CASE WHEN rn%2=0 THEN prod END) OVER (PARTITION BY txn,rndiv2)
ELSE MAX(CASE WHEN rn%2=1 THEN prod END) OVER (PARTITION BY txn,rnplus1div2)
END AS prev_prod,
CASE WHEN rn%2=1
THEN MAX(CASE WHEN rn%2=0 THEN units END) OVER (PARTITION BY txn,rndiv2)
ELSE MAX(CASE WHEN rn%2=1 THEN units END) OVER (PARTITION BY txn,rnplus1div2)
END AS prev_units
from cte
) temp
group by txn
For SQL Server 2012+, use LAG:
select
txn,
sum(
case when prev_prod = 'a' and prod = 'b' and prev_units >= units then 0
when prev_prod = 'a' and prod = 'b' and prev_units < units then units - prev_units
else units
end) units
from
(
select
txn,
prod,
units,
lag(prod) over (partition by txn order by prod) prev_prod,
lag(units) over (partition by txn order by prod) prev_units
from test_data
) temp
group by txn
I decided in the end that a temp table was the best way to go, because I couldn't group on a collation. So I eventually tweaked the code above as it was failing to pick up the spare items correctly
SUM(Units) AS OldUnits
SUM(Units) -
(CASE WHEN
SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) = 0 THEN 0 WHEN
SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END) = 0 THEN 0 WHEN
SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) -
SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END) = 0 THEN
SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) WHEN
(SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) -
SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END)) < 0 THEN
SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) ELSE
SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END) END) AS NewUnits
This was stored in a temptable that I could then collate on Trans as the next step. Works fine for my purposes and helped me overcome a mild irrational fear I have of temptables
I have a huge database with over 4 million rows that look like that:
Customer ID Shop
1 Asda
1 Sainsbury
1 Tesco
2 TEsco
2 Tesco
I need to count customers that within last 4 weeks had shopped in all 3 shops Tesco Sainsbury and Asda. Can you please advice if its possible to do it with subqueries?
This is an example of a "set-within-sets" subquery. You can solve it with aggregation:
select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) > 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0;
This structure is quite flexible. So if you wanted Asda and Tesco but not Sainsbury, then you would do:
select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) = 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0;
EDIT:
If you want a count, then use this as a subquery and count the results:
select count(*)
from (select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) > 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0
) t
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;