Spooling count of data with a condition in oracle - sql

Kindly note that I have the below table, I am trying to spool the count of the sum of the amtpd by grouping the duedt where it is less than or equal to 31-dec-2013, but the amtpd that has the duedt of 31-dec-2013 and that has trndt between 01-dec-2013 and 31-dec-2013, should be less that 10000, in this case the count should be 3.
|duedt| |amtp| |trndt|
|10/31/2013| |2007.1| |10/27/2013|
|10/31/2013| |8442.9| |12/16/2013|
|11/30/2013| |10450| |12/16/2013|
|12/31/2013| |2107.1| |12/16/2013|
|12/31/2013| |8342.9| |3/23/2014|
|12/31/2013| |0| |5/5/2014|
I am using the below query but it is giving me zero count
SELECT COUNT (SUM (amtpd))
FROM ln02rep2
WHERE trndt <= '31-dec-2013'
AND (
(SELECT SUM (amtpd)
FROM ln02rep2
WHERE trndt BETWEEN '01-dec-2013' AND '31-dec-2013'
AND duedt = '31-dec-2013'
)>='10450.00')
GROUP BY by duedt;

Related

How to use CASE WHEN in group by

I want to use group by for the table NRW_MONTH_DATA.
SELECT [OBJECT_ID]
,[YEAR_MONTH]
,[SELLING_AMOUNT]
,[DEFAULT_SELLING_DATA]
,[LOCK_SELLING_AMOUNT]
,[RGCB]
,[ICKZ]
,[YCKZ]
FROM [dbo].[NRW_MONTH_DATA]
IF LOCK_SELLING_AMOUNT is 0 then group by OBJECT_ID and calculate the sum of [RGCB],[ICKZ] and [YCKZ]
SELECT #SELLING_AMOUNT=(ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID
AND YEAR_MONTH >=#SELLING_CENSUS_START_YM
AND YEAR_MONTH <=#SELLING_CENSUS_END_YM
GROUP BY OBJECT_ID
Now I want to add a condition that if LOCK_SELLING_AMOUNT is 1 , I need to
SELECT #SELLING_AMOUNT=ISNULL(SUM(DEFAULT_SELLING_DATA),0)
ELSE use original result to calculate the sum of the 3 columns.
I use CASE WHEN but is seems that I could not use it in group by
SELECT #SELLING_AMOUNT=
CASE LOCK_SELLING_AMOUNT WHEN 1 THEN SELLING_AMOUNT
ELSE (ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
END
The error is like
The column'dbo.NRW_MONTH_DATA.LOCK_SELLING_AMOUNT' in the select list is invalid because the column is not included in the aggregate function or GROUP BY clause.
Thank you in advance.
I need the group by to calculate the sum of them. Each row has an object_id and a LOCK_SELLING_AMOUNT and other columns for one month, I want to use group to calculate the sum during month span.
It works well when I do not consider the LOCK_SELLING_AMOUNT
First, you don't want GROUP BY. So just use:
SELECT #SELLING_WATER = (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;
Now, the problem is that a column can change values on different rows. So, what row does LOCK_SELLING_AMOUNT come from? We could assume it is the same on all rows. Or perhaps you want an aggregation function:
SELECT #SELLING_WATER = (CASE WHEN MAX(LOCK_SELLING_AMOUNT) = 1
THEN MAX(CASE WHEN LOCK_SELLING_AMOUNT = 1 THEN SELLING_AMOUNT END)
ELSE (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
END)
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;

SQL Sum() returning postive and negative values

I'm trying to get SUM() to return the sum of a column summing the positive and negative values in the column. Instead its currently returning one positive value and one negative value, can anyone help?
SELECT
LedgerAP.Period, LedgerAP.Account, SUM(LedgerAP.Amount) Amount
FROM
LedgerAP
WHERE
LedgerAP.Period >= 201500 AND LedgerAP.Account = N'105.71'
GROUP BY LedgerAP.Period, LedgerAP.Account
HAVING SUM(Amount) <> 0
UNION ALL
SELECT
LedgerAR.Period, LedgerAR.Account, SUM(LedgerAR.Amount)
FROM
LedgerAR
WHERE
LedgerAR.Period >= 201500 AND LedgerAR.Account = N'105.71'
GROUP BY LedgerAR.Period, LedgerAR.Account
UNION ALL
SELECT
LedgerEx.Period, LedgerEx.Account, SUM(LedgerEx.Amount)
FROM
LedgerEx
WHERE
LedgerEx.Period >= 201500 AND LedgerEx.Account = N'105.71'
GROUP BY LedgerEx.Period, LedgerEx.Account
UNION ALL
SELECT
LedgerMisc.Period, LedgerMisc.Account, SUM(LedgerMisc.Amount)
FROM
LedgerMisc
WHERE
LedgerMisc.Period >= 201500 AND LedgerMisc.Account = N'105.71'
GROUP BY LedgerMisc.Period, LedgerMisc.Account
I think you need to re-aggregate your results:
with l as (
<your query here>
)
select period, account, sum(amount)
from l
group by period, account;
You can do the same thing with a subquery instead of a CTE.

alternatives to "Having"

I have a SELECT statement that counts the number of instances and then saves in a variable. It has a HAVING clause that does a SUM and a COUNT. However since you have to have a GROUP BY in order to use having, the select statement returns 4 lines that are 1 instead of the total being 4. This then doesn't save the count into the variable as 4 but as 1 which obviously is not what I need so I am looking for an alternative work around.
select count(distinct p1.community)
from
"Database".prospect p1
where
p1.visit_date >= '2013-07-01'
and p1.visit_date <= '2013-09-30'
and p1.division = '61'
group By
p1.community
having
sum(p1.status_1) / count(p1.control_code) >= .16;
This is a reasonable alternative:
select count(*)
from (
select p1.community , sum(p1.status_1) / count(p1.control_code) SomeColumn
from
"Database".prospect p1
where
p1.visit_date >= '2013-07-01'
and p1.visit_date <= '2013-09-30'
and p1.division = '61'
Group By
p1.community
) A
where A.SomeColumn >= .16;

Oracle not returning any data for yesterdays hour

I have the following query:
SELECT d_dtm,
BTS_ID,
CASE WHEN D_DTM = (D_DTM-24/24)
THEN sum(V_ATT_CNT)
END AS "LASTATT",
sum(V_ATT_CNT) as "V_ATT_CNT",
CASE WHEN D_DTM = D_DTM
THEN sum(V_ATT_CNT)
END AS "ATT"
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI
WHERE to_date(D_DTM, 'DD/MM/yyyy') >=
(SELECT TO_DATE(max(D_DTM),'DD/MM/YYYY')
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI)-2
GROUP BY d_dtm,
BTS_ID
HAVING CASE WHEN D_DTM = (D_DTM-24/24)
THEN sum(V_ATT_CNT)
END > 0
But it is not returning any results because of the "having" clause. I know it should return results because all I want it to do is in one column have the V_ATT for the current time period, and in the 2nd column, have the V_ATT 24 hours ago. I've checked the data and I should get results back but can't seem to figure out why this is not working...
If you subtotal (group by) D_DTM, you get one row per date. If you want to compare two dates with each other in the same row you need to do one of two things: either a subquery, or a window function like lag/lead.
I think this is what you're looking for:
SELECT d_dtm,
BTS_ID,
lag(sum(V_ATT_CNT), 1) over (partition by bts_id order by d_dtm)
AS "LASTATT",
sum(V_ATT_CNT) as "V_ATT_CNT"
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI
WHERE to_date(D_DTM, 'DD/MM/yyyy') >=
(SELECT TO_DATE(max(D_DTM),'DD/MM/YYYY')
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI)-2
GROUP BY d_dtm,
BTS_ID
Note that the partition by columns in the lag/over is a subset of the group by columns.
I re-wrote the query using a with statement and two queries. Works pretty fast and gives me the correct results.
WITH FRST
AS ( SELECT D_DTM,
BSM_NM,
SUM (V_ATT_CNT) AS "V_ATT_CNT",
SUM (V_CUST_BLK_CNT) AS "V_CUST_BLK_CNT",
SUM (V_DRP_CALL_CNT) AS "V_DRP_CALL_CNT",
SUM (D_ATT_CNT) AS "D_ATT_CNT",
SUM (D_CUST_BLK_CNT) AS "D_CUST_BLK_CNT",
SUM (D_DRP_CALL_CNT) AS "D_DRP_CALL_CNT"
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI
WHERE D_DTM >=
(SELECT MAX (D_DTM) - NUMTODSINTERVAL (12, 'HOUR')
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI)
GROUP BY D_DTM, BSM_NM),
LST
AS ( SELECT D_DTM,
BSM_NM,
SUM (V_ATT_CNT) AS "V_ATT_CNT",
SUM (V_CUST_BLK_CNT) AS "V_CUST_BLK_CNT",
SUM (V_DRP_CALL_CNT) AS "V_DRP_CALL_CNT",
SUM (D_ATT_CNT) AS "D_ATT_CNT",
SUM (D_CUST_BLK_CNT) AS "D_CUST_BLK_CNT",
SUM (D_DRP_CALL_CNT) AS "D_DRP_CALL_CNT"
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI
WHERE D_DTM >=
(SELECT MAX (D_DTM) - NUMTODSINTERVAL (48, 'HOUR')
FROM DMSN.DS3R_FH_1XRTT_FA_LVL_KPI)
GROUP BY D_DTM, BSM_NM),
EVDOLST
AS ( SELECT D_DTM,
BSM_NM,
SUM (ATT_CNT) AS "ATT_CNT",
SUM (CUST_BLK_CNT) AS "CUST_BLK_CNT",
SUM (DRP_CALL_CNT) AS "DRP_CALL_CNT"
FROM DMSN.DS3R_FH_EVDO_FA_LVL_KPI
WHERE D_DTM >=
(SELECT MAX (D_DTM) - NUMTODSINTERVAL (48, 'HOUR')
FROM DMSN.DS3R_FH_EVDO_FA_LVL_KPI)
GROUP BY D_DTM, BSM_NM),
EVDOFRST
AS ( SELECT D_DTM,
BSM_NM,
SUM (ATT_CNT) AS "ATT_CNT",
SUM (CUST_BLK_CNT) AS "CUST_BLK_CNT",
SUM (DRP_CALL_CNT) AS "DRP_CALL_CNT"
FROM DMSN.DS3R_FH_EVDO_FA_LVL_KPI
WHERE D_DTM >=
(SELECT MAX (D_DTM) - NUMTODSINTERVAL (12, 'HOUR')
FROM DMSN.DS3R_FH_EVDO_FA_LVL_KPI)
GROUP BY D_DTM, BSM_NM)
SELECT t1.D_DTM,
t1.BSM_NM,
t2.V_ATT_CNT AS "LASTV_ATTCNT",
t2.V_CUST_BLK_CNT AS "LASTV_BLKCNT",
t2.V_DRP_CALL_CNT AS "LASTV_DRPCNT",
t1.V_ATT_CNT AS "V_ATT_CNT",
t1.V_CUST_BLK_CNT AS "V_CUST_BLK_CNT",
t1.V_DRP_CALL_CNT AS "V_DRP_CALL_CNT",
t2.D_ATT_CNT AS "LASTD_ATTCNT",
t2.D_CUST_BLK_CNT AS "LASTD_BLKCNT",
t2.D_DRP_CALL_CNT AS "LASTD_DRPCNT",
t1.D_ATT_CNT AS "D_ATT_CNT",
t1.D_CUST_BLK_CNT AS "D_CUST_BLK_CNT",
t1.D_DRP_CALL_CNT AS "D_DRP_CALL_CNT",
t3.ATT_CNT AS "EVDO_ATTCNT",
t3.CUST_BLK_CNT AS "EVDO_BLKCNT",
t3.DRP_CALL_CNT AS "EVDO_DRPCNT",
t4.ATT_CNT AS "EVDO_LASTATTCNT",
t4.CUST_BLK_CNT AS "EVDO_LASTBLKCNT",
t4.DRP_CALL_CNT AS "EVDO_LASTDRPCNT"
FROM FRST t1
INNER JOIN LST t2
ON t1.BSM_NM = t2.BSM_NM
AND t1.D_DTM - NUMTODSINTERVAL (24, 'HOUR') = t2.D_DTM
LEFT OUTER JOIN EVDOLST t4
ON t1.BSM_NM = t4.BSM_NM
AND t1.D_DTM - NUMTODSINTERVAL (24, 'HOUR') = t4.D_DTM
LEFT OUTER JOIN EVDOFRST t3
ON t1.BSM_NM = t3.BSM_NM AND t1.D_DTM = t3.D_DTM

How can I calculate a column data for different conditions using single query in sql server?

I am using below query to count a particular column data based on single condition.
SELECT COUNT(DISTINCT(S.INVOICENO)) AS LESSTWO , YEAR(S.invoicedate) YER,
Month(S.invoicedate) MNTH
FROM SALESDATA S
where S.BILLINGTYPE='INVOICE'
AND (S.invoicedate >='4-1-2009' and S.invoicedate <='4-30-2010')
AND S.TAXABLEAMT <=2000
GROUP BY YEAR(S.invoicedate) ,Month(S.invoicedate)
ORDER BY YEAR(S.invoicedate) ,Month(S.invoicedate)
But I have to calculate for 3 more conditions. Is it possible to count based on 3 conditions(i.e. 2001 - 3000,3001 - 4000, 4001 - 5000,>5000) and I want result set for all the conditions?
Regards,
N.SRIRAM
Untested, but should be about right:
SELECT CASE
WHEN S.TaxableAmt <= 2000 THEN '<=2000'
WHEN S.TaxableAmt <= 3000 THEN '2001-3000'
WHEN S.TaxableAmt <= 4000 THEN '3001-4000'
ELSE '>5000'
END as Bracket,
COUNT(DISTINCT(S.INVOICENO)) AS LESSTWO , YEAR(S.invoicedate) YER,
Month(S.invoicedate) MNTH
FROM SALESDATA S
where S.BILLINGTYPE='INVOICE'
AND (S.invoicedate >='20090401' and S.invoicedate <='20100430')
GROUP BY
CASE
WHEN S.TaxableAmt <= 2000 THEN '<=2000'
WHEN S.TaxableAmt <= 3000 THEN '2001-3000'
WHEN S.TaxableAmt <= 4000 THEN '3001-4000'
ELSE '>5000'
END,
YEAR(S.invoicedate) ,Month(S.invoicedate)
ORDER BY YEAR(S.invoicedate) ,Month(S.invoicedate)
You have to repeat the case expression in the GROUP BY clause (or put it all in a subquery), and I've fixed your date constants so that they're unambiguous.
I think you really need to split up the query into 3 distinct queries - one for each of the conditions you require