Group by within Sub Query - sql

Hi I have the code below which brings through a total by due and complete as well as the date. However I want to summarize by date, please can someone assist?
SELECT CONVERT(varchar(15), GRLastDt, 111) as Date_,
(
SELECT COUNT(*) AS Expr1
FROM dbo.AN_Admin_VendorReturns_090_Final
WHERE (Complete = 'X') AND (CONVERT(varchar(15), GRLastDt, 111) >= GETDATE() - 60)
) AS Complete,
(
SELECT COUNT(*) AS Expr1
FROM dbo.AN_Admin_VendorReturns_090_Final AS AN_Admin_VendorReturns_090_Final_1
WHERE (Complete <> 'X') AND (CONVERT(varchar(15), GRLastDt, 111) >= GETDATE() - 60)
) AS DUE
FROM dbo.AN_Admin_VendorReturns_090_Final
group by CONVERT(varchar(15), GRLastDt, 111)

SELECT CGRLastDt as Date_,
SUM(CASE WHEN Complete = 'X' Then 1 Else 0 END) AS Complete,
SUM(CASE WHEN Complete <> 'X' Then 1 Else 0 END) AS Due
FROM dbo.AN_Admin_VendorReturns_090_Final
WHERE GRLastDt >= GETDATE() - 60
GROUP BY GRLastDt
Please note that I haven't validated this SQL for syntax and doing this in notepad.

Related

How can I include more columns other than just percentage column in my sql query result?

When I use the below query I only get percentage column but I want the (buyer_id, buyer_name, created_date,total_work_orders_with_gtv_first_60_days, total_gtv_first_60_days, total_net_amount_first_60_days) to show as columns too. Would really appreciate your help please.
WITH results_cte AS (
SELECT
b.buyer_id,
b.buyer_name,
CAST(b.created_date AS DATE) AS created_date,
COALESCE(wo.total_work_orders_with_gtv_first_60_days, 0) AS total_work_orders_with_gtv_first_60_days,
COALESCE(wo.total_gtv_first_60_days, 0) AS total_gtv_first_60_days,
COALESCE(wo.total_net_amount_first_60_days, 0) AS total_net_amount_first_60_days
FROM dw.buyer b
LEFT JOIN (SELECT wo.buyer_id,
COUNT(CASE WHEN wo.gtv_date < DATEADD(DAY, 60, b.created_date) THEN wo.work_order_id ELSE NULL END) AS total_work_orders_with_gtv_first_60_days,
SUM(CASE WHEN wo.gtv_date < DATEADD(DAY, 60, b.created_date) THEN wo.gtv ELSE NULL END) AS total_gtv_first_60_days,
SUM(CASE WHEN wo.gtv_date < DATEADD(DAY, 60, b.created_date) THEN wo.net_amount ELSE NULL END) AS total_net_amount_first_60_days
FROM dw.work_order wo
JOIN dw.buyer b
ON wo.buyer_id = b.buyer_id
WHERE wo.gtv > 0
GROUP BY wo.buyer_id) wo
ON b.buyer_id = wo.buyer_id
WHERE b.buyer_segmentation = 'S - Self-Service'
AND b.status = 'Active'
AND b.created_date >= DATEADD(YEAR, -1, GETDATE())
)
SELECT (SELECT CAST(count(DISTINCT buyer_id) AS float) FROM results_cte WHERE total_work_orders_with_gtv_first_60_days > 0)
/ (SELECT CAST(count(DISTINCT buyer_id) AS float) FROM results_cte ) AS percentage

SqlServer : Number of 'open' issues on a daily basis

I'm getting an error with this query "Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ';'" and have been at it for a few hours now. I'm trying to calculate 'open' issues on given days (ideally between a timeframe but for now just on dates that have entries).
My Data is simplified as:
IssueID, CreationDate, CompletionDate
I'd like to tally open issues which is when Year(CompletionDate)=1900 and they are cumulative while they are open, ie: if yesterday there was 1 issue open and today has 1 issue open as well, then today's count of open is 2. They should drop off once they are resolved (Year(CompletionDate) <> 1900). Please help I think i'm close?
SELECT
x.created_date,
aOpen + Open_Issue - Resolved_Issue as totopen
from(
select
convert(varchar(10), cast(i.CreationDate as date), 101) as created_date,
sum( case when YEAR(i.CompletionDate)='1900' then 1 else 0 end) as aOpen,
sum( case when YEAR(i.CompletionDate)<>'1900' AND (i.CompletionDate >=
i.CreationDate) then 1 else 0 end ) as Open_Issue,
coalesce(tot,0) as Resolved_Issue
FROM Issues i
LEFT JOIN (SELECT count(IssueID) as tot, CompletionDate as resolved
from Issues where YEAR(CompletionDate)<>'1900' group by CompletionDate,
count(IssueID))x
ON i.CreationDate = x.resolved);
UPDATE
I have this returning output correctly on a daily basis only, as in it is not accounting for previous, still open issues (Legacy_Open_Issue) and adding them.
SELECT
created_date,
aOpen_Today + Legacy_Open_Issue - Resolved_Issue as totopen
FROM(
SELECT
convert(varchar(10), cast(i.CreationDate as date), 101) as created_date,
sum( case when YEAR(i.CompletionDate)=1900 then 1 else 0 end) as aOpen_Today,
sum( case when (YEAR(i.CompletionDate)<>1900 AND (i.CompletionDate >= i.CreationDate)) then 1 else 0 end ) as Legacy_Open_Issue,
coalesce(tot,0) as Resolved_Issue
FROM Issues i
LEFT JOIN (
SELECT count(IssueID) as tot, CompletionDate as resolved
FROM Issues
WHERE YEAR(CompletionDate)<>1900 group by CompletionDate
)x ON x.resolved = i.CreationDate
GROUP BY convert(varchar(10), cast(i.CreationDate as date), 101), coalesce(tot,0)
) AS y;
My Data is
IssueID CreationDate CompletionDate
1 1/15/2019 1/1/1900
2 1/16/2019 1/17/2019
3 1/16/2019 1/1/1900
4 1/20/2019 1/21/2019
5 1/28/2019 1/1/1900
6 1/30/2019 1/1/1900
My Output is
created_date totopen
1/15/2019 1
1/16/2019 2
1/20/2019 1
1/28/2019 1
1/30/2019 1
My Output SHOULD be
created_date totopen
1/15/2019 1
1/16/2019 3
1/20/2019 3
1/28/2019 3
1/30/2019 4
thank you for your help
You need to alias the derived table such as:
SELECT
x.created_date,
aOpen + Open_Issue - Resolved_Issue as totopen
from(
select
convert(varchar(10), cast(i.CreationDate as date), 101) as created_date,
sum( case when YEAR(i.CompletionDate)='1900' then 1 else 0 end) as aOpen,
sum( case when YEAR(i.CompletionDate)<>'1900' AND (i.CompletionDate >=
i.CreationDate) then 1 else 0 end ) as Open_Issue,
coalesce(tot,0) as Resolved_Issue
FROM Issues i
LEFT JOIN (SELECT count(IssueID) as tot, CompletionDate as resolved
from Issues where YEAR(CompletionDate)<>'1900' group by CompletionDate,
count(IssueID))x
ON i.CreationDate = x.resolved) as DT;
Derived tables require an alias. You need to add "AS {alias}" to the end of your query. You should also format and line break the code for better legibility.
SELECT
x.created_date,
aOpen + Open_Issue - Resolved_Issue as totopen
from(
select
convert(varchar(10), cast(i.CreationDate as date), 101) as created_date,
sum( case when YEAR(i.CompletionDate)=1900 then 1 else 0 end) as aOpen,
sum( case when YEAR(i.CompletionDate)<>1900 AND (i.CompletionDate >= i.CreationDate) then 1 else 0 end ) as Open_Issue,
coalesce(tot,0) as Resolved_Issue
FROM Issues i
LEFT JOIN (
SELECT count(IssueID) as tot, CompletionDate as resolved
from Issues
where YEAR(CompletionDate)<>1900
group by CompletionDate
)x ON i.CreationDate = x.resolved
group by convert(varchar(10), cast(i.CreationDate as date), 101)
) AS y;
Also, SO generally doesn't do multiple questions per post. I addressed the error/alias issue, but if you have results issues, you should post a new question with sample data and expected results.
To be able to use date ranges and ensure there are no gaps in your output (ie. on dates where no tickets were created), you may want to consider using a Dates fact / reference table like this:
Select d.Date
, count(i.IssueID) as TotalOpen
, sum(case when DateDiff(DD, d.Date, cast(i.CreationDate as date)) = 0 then 1 else 0 end) as NewOpened
, sum(case when DateDiff(DD, d.Date, cast(i.CompletionDate as date)) = 0 then 1 else 0 end) as NewClosed
From Dates d
Left join Issues i
on d.Date between convert(varchar(10), cast(i.CreationDate as date), 101) and
case when YEAR(i.CompletionDate)='1900' then d.Date else i.CompletionDate end
Group by d.Date
Fill the Dates table with all the dates you'd want to display results for (ie. everyday, weekdays) or use a where clause to filter the date range / pattern.

SQL Server issue with select and group by with calculated columns

I have this SQL I am trying to build:
select
a.Name,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate < GETDATE()) AS Due,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate = GETDATE()) AS Today,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate = DATEADD(DAY, 1, GETDATE())) AS Expected,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate > DATEADD(DAY, 1, GETDATE())) AS Planned
from Centers AS a
INNER JOIN Collections AS b
ON a.Id = b.CenterId
GROUP BY a.Name
But I get an error:
Column 'Collections.PlannedCollectionDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know I could do something like this:
select
a.Name,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate < GETDATE()) AS Due,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate = GETDATE()) AS Today,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate = DATEADD(DAY, 1, GETDATE())) AS Expected,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate > DATEADD(DAY, 1, GETDATE())) AS Planned
from Centers AS a
But I assume that is slower because I have to do multiple selects from the same table (Collections).
So, my question is, what can I do to make my first query work? I don't think grouping by PlannedCollectionDate is right, because it will mess up my count
I think you want conditional aggregation:
select ce.Name,
SUM(CASE WHEN co.PlannedCollectionDate < GETDATE() THEN 1 ELSE 0 END) AS Due,
SUM(CASE WHEN co.PlannedCollectionDate = GETDATE() THEN 1 ELSE 0 END) AS Today,
SUM(CASE WHEN co.PlannedCollectionDate = DATEADD(DAY, 1, GETDATE()) THEN 1 ELSE 0 END) AS Expected,
SUM(CASE WHEN co.PlannedCollectionDate > DATEADD(DAY, 1, GETDATE()) THEN 1 ELSE 0 END) AS Planned
from Centers ce join
Collections co
on ce.Id = co.CenterId
group by ce.Name;
This implements what you have written. Do note the use of meaningful table aliases.
However, it will not do what you want, because GETDATE() has a time component. To fix that, convert it to a date:
select ce.Name,
SUM(CASE WHEN co.PlannedCollectionDate < CONVERT(DATE, GETDATE()) THEN 1 ELSE 0 END) AS Due,
SUM(CASE WHEN co.PlannedCollectionDate = CONVERT(DATE, GETDATE()) THEN 1 ELSE 0 END) AS Today,
SUM(CASE WHEN co.PlannedCollectionDate = DATEADD(DAY, 1, CONVERT(DATE, GETDATE())) THEN 1 ELSE 0 END) AS Expected,
SUM(CASE WHEN co.PlannedCollectionDate > DATEADD(DAY, 1, CONVERT(DATE, GETDATE())) THEN 1 ELSE 0 END) AS Planned
from Centers ce join
Collections co
on ce.Id = co.CenterId
group by ce.Name;
Note that this assumes that PlannedCollectionDate does not have a time component.

Revenue for two months date wise

I am trying to get data for last 2 month ...but the query does not give perfect result....
SELECT DAY(table_A.PaymentDate) as date1 ,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP) - 1
then CAST(SUM(table_A.Total_Amount) AS INT)
else 0
end) AS last_month_CNT,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP)
then CAST(SUM(table_A.Total_Amount) As INT)
else 0
end) as This_month_CNT
FROM Tbl_Pan_Paymentdetails table_A
FULL OUTER JOIN Tbl_Pan_Paymentdetails table_B
ON table_A.PaymentDate=table_B.PaymentDate
WHERE YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND
table_A.PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY
DAY(table_A.PaymentDate) ,MONTH(table_A.PaymentDate)
order by
DAY(table_A.PaymentDate);
Move the entire case expression inside the sum function and don't include the month in the group by. Also, the full outer join seems unnecessary so I removed it.
This should be what you are looking for:
SELECT
DAY(PaymentDate) as date1 ,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP)-1 THEN CAST(Total_Amount AS INT) ELSE 0 END) AS last_month_CNT,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP) THEN CAST(Total_Amount AS INT) ELSE 0 END) AS This_month_CNT
FROM Tbl_Pan_Paymentdetails
WHERE YEAR(PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY DAY(PaymentDate)
ORDER BY DAY(PaymentDate);

Duplicates from an SQL Query

I have a dataset I retrieve from multiple joins. I have used SELECT DISTINCT in my statements but I still see duplicates in the result set. Here is the code:
SELECT DISTINCT Account
, PayoffAmtDOL as 'Payoff Amount DOL'
, PayoffAmtLOG as 'Payoff Amount LOG'
, PayoffAmountLive as 'Payoff Amount Live'
, [Difference]
, PrincipalBalance as 'Principal Balance'
, CreationDate as 'Date Entered System'
, CACSState as 'CACS State at Entry'
, PaymentsMade AS 'Payments Made'
, TotalPaymentAmount as 'Total Payment Amount'
, 'Liquidation Percentage' = CASE WHEN PayoffAmountLive = 0 THEN 1
WHEN ISNULL([Difference],0) = ISNULL(PayoffAmtDOL, 0) THEN 1
WHEN ISNULL([Difference],0) < 0 AND ISNULL(PayoffAmtDOL, 0) > 0 THEN 0
WHEN ISNULL([Difference],0) > 0 AND ISNULL(PayoffAmtDOL, 0) < 0 THEN 1
WHEN ISNULL([Difference],0) > ISNULL(PayoffAmtDOL, 0) THEN 1
WHEN [Difference] > 0 AND ISNULL(PayoffAmtDOL, 0) = 0 THEN 1
WHEN ISNULL(PayoffAmtDOL, 0) = 0 THEN 0
ELSE ISNULL([Difference],0)/ISNULL(PayoffAmtDOL, 0) END
, Cnt = 1
FROM
(
SELECT DISTINCT a.Account,
c.PayoffAmtDOL,
c.PayoffAmtLOG,
(ISNULL(c.PayoffAmtCACS, cacs.payoff_amt)) as 'PayoffAmountLive',
(ISNULL(c.PayoffAmtDOL, 0) - (ISNULL(c.PayoffAmtCACS , ISNULL(cacs.payoff_amt, 0)))) as 'Difference',
c.PrincipalBalance,
c.CreationDate,
c.CACSState,
(SELECT COUNT(PaymentID)
FROM tblATLPaymentInfo p
WHERE p.AccountID = a.AccountID
AND CONVERT(DATETIME, CONVERT(VARCHAR(10), p.CreationDate, 101)) >= '1/1/2014'
AND CONVERT(DATETIME, CONVERT(VARCHAR(10), p.CreationDate, 101)) <= '3/27/2014'
) as 'PaymentsMade',
(SELECT SUM(PaymentAmount)
FROM tblATLPaymentInfo p
WHERE p.AccountID = a.AccountID
AND CONVERT(DATETIME, CONVERT(VARCHAR(10), p.CreationDate, 101)) >= '1/1/2014'
AND CONVERT(DATETIME, CONVERT(VARCHAR(10), p.CreationDate, 101)) <= '3/27/2014'
) as 'TotalPaymentAmount'
FROM tblATLAcctInfo a
RIGHT JOIN tblATLClaimInfo c
ON c.AccountID = a.AccountID
LEFT JOIN SCFLOKYDCMSQL03.CACS_DM.dbo.Cacs_Info cacs
ON cacs.Account = a.Account
WHERE CONVERT(DATETIME, CONVERT(VARCHAR(10), c.CreationDate, 101)) >= '1/1/2014'
AND CONVERT(DATETIME, CONVERT(VARCHAR(10), c.CreationDate, 101)) <= '3/27/2014'
AND c.ClaimTypeID = (SELECT DISTINCT ClaimTypeID FROM tblATLClaimType WHERE ClaimType = 'N02 - Claims')
) a
ORDER BY Account
Here is an example of the duplicate rows:
AccountID DateEntered
123 01/19/2014
123 01/21/2014
345 02/1/2014
345 02/10/2014
The difference between appears to be the date entered. Maybe selecting the Row_Number() and then deleting the later date could be a solution
DISTINCT should not return multiple rows.. there should be at least one column that is different in each row, no? With character data, sometimes one can be fooled by non-visible differences, such as trailing spaces. Not sure if that is the case here, though.
Can you give an example of the duplicate rows?
OK, I see your edit. You have to select which of the dates to display. Try this to get the earliest date per AccountID:
SELECT AccountID, MIN(DateEntered) AS DateEntered
FROM ....
GROUP BY AccountID
ORDER BY AccountID
You can add more columns in the SELECT, as long as they are distinct you will not get more rows.
If you want, you can add COUNT(*) to the select to get the number of rows grouped.
DISTINCT will only reject lines that are exact duplicates, the DateEntered is different on each ID. If you want the latest, use Max(DateEntered)