how to make multi column with multi where condition - sql-server

i have 3 SQL statement i want to merge them into one but each of them has its own where condition how can i merge them into one query that show the result for each of them to be like
Project Code||Balance||Salaries||Materials
1st
SELECT
ProjectCode,
SUM (- 1 *(CreditAm) +(DebitAm)) AS Balance
FROM
[dbo].[AcDetail]
WHERE
AcCode IN (
401000,
402000,
403000,
404000,
405000,
406000,
407000,
499999
)
AND BranchCode = 'WP'
AND TDate >= '2016-01-01'
AND TDate <= '2016-12-31'
GROUP BY
ProjectCode
2nd
SELECT
ProjectCode,
SUM (- 1 *(CreditAm) +(DebitAm)) AS Materials
FROM
[dbo].[AcDetail]
WHERE
AcCode IN (600001, 600002, 600151)
AND BranchCode = 'WP'
AND TDate >= '2016-01-01'
AND TDate <= '2016-12-31'
GROUP BY
ProjectCode
3rd
SELECT
ProjectCode,
SUM (- 1 *(CreditAm) +(DebitAm)) AS Salaries
FROM
[dbo].[AcDetail]
WHERE
AcCode IN (
650001,
650005,
650006,
650007,
650008,
650009,
650010,
650020,
650021,
650022,
650023,
650024,
650025,
650026,
650027
)
AND BranchCode = 'WP'
AND TDate >= '2016-01-01'
AND TDate <= '2016-12-31'
GROUP BY
ProjectCode
ORDER BY
ProjectCode

Use Conditional SUM. Sum the values only when the Accode matches the list
SELECT ProjectCode,
Sum (CASE
WHEN AcCode IN ( '401000', '402000', '403000', '404000',
'405000', '406000', '407000', '499999' ) THEN -1 * ( CreditAm ) + ( DebitAm )
ELSE 0
END) AS Balance,
Sum (CASE
WHEN AcCode IN ( '600001', '600002', '600151' ) THEN -1 * ( CreditAm ) + ( DebitAm )
ELSE 0
END) AS Materials,
Sum (CASE
WHEN AcCode IN ( '650001', '650005', '650006', '650007',
'650008', '650009', '650010', '650020',
'650021', '650022', '650023', '650024',
'650025', '650026', '650027' ) THEN -1 * ( CreditAm ) + ( DebitAm )
ELSE 0
END) AS Salaries
FROM [dbo].[AcDetail]
WHERE AcCode IN ( '401000', '402000', '403000', '404000',
'405000', '406000', '407000', '499999',
'600001', '600002', '600151', '650001',
'650005', '650006', '650007', '650008',
'650009', '650010', '650020', '650021',
'650022', '650023', '650024', '650025',
'650026', '650027' )
GROUP BY ProjectCode

We can done it using OUTER APPLY as well by making different set for each column as below:
SELECT D.ProjectCode,
ISNULL(SUM(B.Balance), 0) AS Balance,
ISNULL(SUM(M.Materials), 0) AS Materials,
ISNULL(SUM(S.Salaries), 0) AS Salaries
FROM [dbo].[AcDetail] AS D
OUTER APPLY (SELECT (- 1 *(CreditAm) +(DebitAm)) AS Balance
FROM [dbo].[AcDetail]
WHERE AcCode IN ('401000', '402000', '403000', '404000',
'405000', '406000', '407000', '499999')
AND AcCode = D.AcCode
AND TDate = D.TDate
AND ProjectCode = D.ProjectCode) AS B --Balance
OUTER APPLY (SELECT (- 1 *(CreditAm) +(DebitAm)) AS Materials
FROM [dbo].[AcDetail]
WHERE AcCode IN ('600001', '600002', '600151')
AND AcCode = D.AcCode
AND TDate = D.TDate
AND ProjectCode = D.ProjectCode) AS M -- Materials
OUTER APPLY (SELECT (- 1 *(CreditAm) +(DebitAm)) AS Salaries
FROM [dbo].[AcDetail]
WHERE AcCode IN ('650001', '650005', '650006', '650007', '650008', '650009',
'650010', '650020','650021', '650022', '650023', '650024',
'650025', '650026', '650027')
AND AcCode = D.AcCode
AND TDate = D.TDate
AND ProjectCode = D.ProjectCode) AS S --Salary
WHERE D.BranchCode = 'WP'
AND D.AcCode IN ('401000', '402000', '403000', '404000', '405000', '406000', '407000',
'499999','600001', '600002', '600151', '650001', '650005', '650006', '650007',
'650008','650009', '650010', '650020', '650021', '650022', '650023', '650024',
'650025','650026', '650027')
AND D.TDate >= '2016-01-01'
AND D.TDate <= '2016-12-31'
GROUP BY D.ProjectCode
ORDER BY D.ProjectCode

Related

Query never finishes

So I have a query for a report that never finishes. I've allowed it to run for upwards of 20+ mins without completing. Here is the query:
DECLARE #start DATE, #end DATE
SET #start = '7-1-2019'
SET #end = '8-20-2019'
SELECT cg.*
,ba.std_StandardAcctNo AS bonus_acct
FROM [CustSalesTrend_Growth] cg
LEFT JOIN (
SELECT DISTINCT std_standardacctno
FROM [CustSalesTrend_Growth]
WHERE eleph_Period_Date BETWEEN #Start
AND #End
OR ideal_Period_Date BETWEEN #Start
AND #End
) ba ON ba.std_StandardAcctNo = cg.std_StandardAcctNo
AND cg.Period_Date >= #Start
AND cg.Period_Date <= #End
WHERE [Appearance_Count] <> 0
AND Period_gp <> 0
ORDER BY cg.std_StandardAcctNo
One of my first steps in diagnosing this is doing a simple select * on the view being referenced (CustSalesTrend_Growth) and it will finish running in about 30 seconds on average, pulling 12k records. Given this, I'm a little perplexed as to how the preceding query could add so much complexity to the execution, to the point that it never finishes. In my mind, the query above is relatively simple, so any ideas as to why this is happening?
EDIT: query for the view CustSalesTrend_Growth
CREATE VIEW [dbo].[CustSalesTrend_Growth]
AS
WITH basedata
AS (
SELECT DISTINCT a.order_num
,a.Period_Date
,a.year AS std_the_year
,a.Month AS std_the_month
,a.customer_alias AS std_StandardAcctNo
,b.SalesPerson_name
,isnull(ac.counter, 0) [Appearance_Count]
,isnull(b.[Year], 0) [The_Year]
,isnull(b.[Month], 0) [The_Month]
,isnull(b.Customer_Alias, 0) [CustomerName]
,sum(isnull(b.Gallons, 0)) [Gallon_Qty]
,sum(isnull(b.[Total Sale], 0)) [Total_Sale]
,sum(isnull(b.[Gross Profit], 0)) [Total_Gross_Profit]
FROM (
SELECT DISTINCT a.year
,a.month
,b.Customer_Alias
,convert(INTEGER, convert(VARCHAR(4), a.Year) + right('00' + convert(VARCHAR(2), a.month), 2)) AS order_num
,convert(DATE, convert(VARCHAR(2), a.Month) + '/01/' + convert(VARCHAR(4), a.Year)) AS Period_Date
FROM Complete_Sales_V2 a
JOIN (
SELECT DISTINCT Customer_Alias
FROM Complete_Sales_V2
) b ON 1 = 1
) a
JOIN PDI_Warehouse_2049_01.dbo.Appearance_Count ac ON a.Customer_Alias = ac.customer_alias
LEFT JOIN Complete_Sales_V2 b ON a.Customer_Alias = b.Customer_Alias
AND a.Month = b.Month
AND a.Year = b.Year
GROUP BY a.order_num
,a.Period_Date
,a.year
,a.Month
,a.Customer_Alias
,b.SalesPerson_Name
,ac.counter
,b.[Year]
,b.[Month]
,b.Customer_Alias
)
,saleslist
AS (
SELECT DISTINCT SalesPerson_Name
,Appearance_Count
,Period_Date
,std_the_month
,std_the_year
,std_StandardAcctNo
,isnull(sum(Total_Gross_Profit), 0) Period_GP
FROM basedata
GROUP BY SalesPerson_Name
,Appearance_Count
,Period_Date
,std_StandardAcctNo
,std_the_month
,std_the_year
)
,core_GP
AS (
SELECT DISTINCT a.Customer_Alias
,convert(DATE, convert(VARCHAR(2), a.month) + '/01/' + convert(VARCHAR(4), a.year)) AS Period_Date
,sum(a.[Gross Profit]) AS Period_GP
FROM Complete_Sales_V2 a
JOIN PDI_Warehouse_2049_01.dbo.appearance_count ac ON ac.customer_alias = a.Customer_Alias
GROUP BY counter
,convert(DATE, convert(VARCHAR(2), a.month) + '/01/' + convert(VARCHAR(4), a.year))
,a.Customer_Alias
)
,GroupedData
AS (
SELECT DISTINCT cgp.std_StandardAcctNo
,cgp.Period_Date
,sum(cgp.[Total_Gross_Profit]) AS Period_GP
,Appearance_Count
FROM basedata cgp
GROUP BY cgp.std_StandardAcctNo
,cgp.Period_Date
,Appearance_Count
)
,GP_Grouping
AS (
SELECT std_StandardAcctNo
,min(Period_Date) AS range_start
,max(Period_Date) AS range_end
,count(*) AS range_count
,GP_group
FROM (
SELECT std_StandardAcctNo
,Period_Date
,CASE
WHEN Period_GP = 0
THEN 0
ELSE 1
END AS GP_Group
,row_number() OVER (
PARTITION BY std_StandardAcctNo
,CASE
WHEN Period_GP = 0
THEN 0
ELSE 1
END ORDER BY Period_Date
) AS rn
,row_number() OVER (
PARTITION BY std_StandardAcctNo
,CASE
WHEN Period_GP = 0
THEN 0
ELSE 1
END ORDER BY Period_Date
) - row_number() OVER (
PARTITION BY std_StandardAcctNo ORDER BY Period_Date
) AS grp
,row_number() OVER (
PARTITION BY std_StandardAcctNo ORDER BY Period_Date
) AS grp2
FROM GroupedData
) a
GROUP BY std_StandardAcctNo
,grp
,GP_Group
)
,GP_Group2
AS (
SELECT gd.*
,max(gpg_prev.range_end) AS last_zero_group -- , gpg.range_count
FROM GroupedData gd
LEFT JOIN GP_Grouping gpg ON gd.std_StandardAcctNo = gpg.std_StandardAcctNo
AND gd.Period_Date BETWEEN gpg.range_start
AND gpg.range_end
LEFT JOIN (
SELECT *
FROM GP_Grouping
WHERE GP_Group = 0
AND range_count >= 12
) gpg_prev ON gpg_prev.std_StandardAcctNo = gd.std_StandardAcctNo
AND gpg.range_start > gpg_prev.range_end
GROUP BY gd.std_StandardAcctNo
,Period_Date
,Period_GP
,Appearance_Count
,gpg.range_count
)
,GP_Group3
AS (
SELECT gd.*
,Appearance_Cnt_Rel = CASE
WHEN gd.last_zero_group IS NULL
THEN Appearance_Count
ELSE ROW_NUMBER() OVER (
PARTITION BY gd.std_StandardAcctNo
,gd.last_zero_group ORDER BY gd.Period_Date
)
END
FROM GP_Group2 gd
)
,almost_done
AS (
SELECT DISTINCT bd.order_num
,bd.Period_Date
,bd.std_the_year
,bd.std_the_month
,bd.std_StandardAcctNo
,CASE
WHEN bd.[Appearance_Count] > 0
THEN bd.[Appearance_Count]
WHEN isnull(c.Appearance_Count, 0) > 0
THEN c.Appearance_Count + 1
WHEN isnull(d.Appearance_Count, 0) > 0
THEN d.Appearance_Count + 2
WHEN isnull(e.Appearance_Count, 0) > 0
THEN e.Appearance_Count + 3
ELSE 0
END AS Appearance_Count
,bd.[The_Year]
,bd.[The_Month]
,bd.[CustomerName]
,bd.[Gallon_Qty]
,bd.[Total_Sale]
,isnull(c.Appearance_Count, 0) AS Prev_Count
,isnull(d.Appearance_Count, 0) AS month2_Count
,isnull(e.Appearance_Count, 0) AS month3_Count
,CASE
WHEN bd.SalesPerson_Name IS NOT NULL
THEN bd.SalesPerson_Name
WHEN c.SalesPerson_Name IS NOT NULL
THEN c.SalesPerson_Name
WHEN d.SalesPerson_Name IS NOT NULL
THEN d.SalesPerson_Name
WHEN e.SalesPerson_Name IS NOT NULL
THEN e.SalesPerson_Name
ELSE 'NA'
END [SalesPerson]
,CASE
WHEN bd.[Appearance_Count] IS NULL
AND c.[Appearance_Count] IS NULL
AND d.[Appearance_Count] IS NULL
THEN e.Period_GP
ELSE 0
END [Lost_Gross_Profit]
,CASE
WHEN bd.Appearance_Count = 1
THEN bd.Total_Gross_Profit
ELSE 0
END AS 'New_Cust_GP'
,CASE
WHEN bd.Appearance_Count <= 12
THEN bd.Total_Gross_Profit
ELSE 0
END AS 'Young_Cust_GP'
,CASE
WHEN bd.Appearance_Count > 12
THEN bd.Total_Gross_Profit
ELSE 0
END AS 'Old_Cust_GP'
,ROW_NUMBER() OVER (
PARTITION BY bd.std_StandardAcctNo
,bd.std_The_Year
,bd.std_The_Month ORDER BY (bd.std_StandardAcctNo) DESC
) AS UNI_Period
,bd.Total_Gross_Profit AS SalesP_GP
,isnull(cg.Period_gp, 0) AS Period_gp
,CASE
WHEN isnull(b_prev.Period_gp, 0) > 0
THEN isnull(b_prev.Period_gp, 0)
WHEN isnull(d.Period_gp, 0) > 0
THEN isnull(d.Period_gp, 0)
WHEN isnull(e.Period_gp, 0) > 0
THEN isnull(e.Period_gp, 0)
ELSE 0
END AS Prev_Period_GP
,h.Mat_MoM_Shift
,CASE
WHEN isnull(b_prev.Period_gp, 0) > 0
THEN isnull(b_prev.Period_gp, 0)
WHEN isnull(d.Period_gp, 0) > 0
THEN isnull(d.Period_gp, 0)
WHEN isnull(e.Period_gp, 0) > 0
THEN isnull(e.Period_gp, 0)
ELSE 0
END * h.Mat_MoM_Shift AS Expected_GP
,isnull(c.Period_gp, 0) AS True_Prev_GP
,isnull(d.Period_gp, 0) AS True_2month_GP
,isnull(e.Period_gp, 0) AS True_3month_GP
,ideal_candidate = CASE
WHEN ((isnull(c.Period_gp, 0) + isnull(d.Period_gp, 0) + isnull(bd.Total_Gross_Profit, 0)) / 3 >= 800)
AND isnull(c.Period_gp, 0) >= 150
AND isnull(d.Period_gp, 0) >= 150
AND isnull(bd.Total_Gross_Profit, 0) >= 150
THEN 'Y'
ELSE 'N'
END
,eleph_candidate = CASE
WHEN ((isnull(c.Period_gp, 0) + isnull(d.Period_gp, 0) + isnull(bd.Total_Gross_Profit, 0)) / 3 >= 5000)
AND isnull(c.Period_gp, 0) >= 1000
AND isnull(d.Period_gp, 0) >= 1000
AND isnull(bd.Total_Gross_Profit, 0) >= 1000
THEN 'Y'
ELSE 'N
'
END
FROM basedata bd
LEFT JOIN core_GP b_prev ON bd.std_StandardAcctNo = b_prev.Customer_Alias
AND b_prev.Period_Date = dateadd(month, - 1, bd.Period_Date)
LEFT JOIN saleslist c ON c.std_StandardAcctNo = bd.std_StandardAcctNo
AND c.Period_Date = dateadd(month, - 1, bd.Period_Date)
AND CASE
WHEN bd.SalesPerson_Name IS NOT NULL
THEN bd.SalesPerson_Name
ELSE c.SalesPerson_Name
END = c.SalesPerson_Name
LEFT JOIN saleslist d ON d.std_StandardAcctNo = bd.std_StandardAcctNo
AND d.Period_Date = dateadd(month, - 2, bd.Period_Date)
AND CASE
WHEN bd.SalesPerson_Name IS NOT NULL
THEN bd.SalesPerson_Name
WHEN c.SalesPerson_Name IS NOT NULL
THEN c.SalesPerson_Name
ELSE d.SalesPerson_Name
END = d.SalesPerson_Name
LEFT JOIN saleslist e ON e.std_StandardAcctNo = bd.std_StandardAcctNo
AND e.Period_Date = dateadd(month, - 3, bd.Period_Date)
AND CASE
WHEN bd.SalesPerson_Name IS NOT NULL
THEN bd.SalesPerson_Name
WHEN c.SalesPerson_Name IS NOT NULL
THEN c.SalesPerson_Name
WHEN d.SalesPerson_Name IS NOT NULL
THEN d.SalesPerson_Name
ELSE e.SalesPerson_Name
END = e.SalesPerson_Name
LEFT JOIN RicoCustom.dbo.[Rico_Global_Monthly] h ON h.month = bd.std_the_month
LEFT JOIN core_GP cg ON bd.std_StandardAcctNo = cg.Customer_Alias
AND cg.Period_Date = bd.Period_Date
)
,get_ideal
AS (
SELECT DISTINCT min(ad.Period_Date) AS ideal_Period_Date
,ad.std_StandardAcctNo
,rc.last_zero_group
FROM almost_done ad
LEFT JOIN GP_Group3 rc ON rc.Period_Date = ad.Period_Date
AND rc.std_StandardAcctNo = ad.std_StandardAcctNo
AND rc.Period_GP = ad.Period_gp
WHERE ideal_candidate = 'Y'
AND (
rc.Appearance_Cnt_Rel BETWEEN 3
AND 6
)
GROUP BY ad.std_StandardAcctNo
,rc.last_zero_group
)
,get_elephant
AS (
SELECT DISTINCT min(ad.Period_Date) AS eleph_Period_Date
,ad.std_StandardAcctNo
,rc.last_zero_group
FROM almost_done ad
LEFT JOIN GP_Group3 rc ON rc.Period_Date = ad.Period_Date
AND rc.std_StandardAcctNo = ad.std_StandardAcctNo
AND rc.Period_GP = ad.Period_gp
WHERE eleph_candidate = 'Y'
AND (
rc.Appearance_Cnt_Rel BETWEEN 3
AND 36
)
GROUP BY ad.std_StandardAcctNo
,rc.last_zero_group
)
SELECT rc.Appearance_Cnt_Rel
,gi.ideal_Period_Date
,ge.eleph_Period_Date
,ad.*
FROM almost_done ad
LEFT JOIN GP_Group3 rc ON rc.Period_Date = ad.Period_Date
AND rc.std_StandardAcctNo = ad.std_StandardAcctNo
AND rc.Period_GP = ad.Period_gp
LEFT JOIN get_ideal gi ON ad.std_StandardAcctNo = gi.std_StandardAcctNo
AND ad.Period_Date = gi.ideal_Period_Date
LEFT JOIN get_elephant ge ON ad.std_StandardAcctNo = ge.std_StandardAcctNo
AND ad.Period_Date = ge.eleph_Period_Date
WHERE order_num > 201001
The indexing I have exists on the source table, Complete_Sales_V2. It is as follows:
index desc:
clustered, unique, primary key located on PRIMARY
index keys:
Customer_Alias, SalesPerson_Name, year, month, Invoice_Number
Since you say you can query the view I suggest selecting your view into a temp table prior to performing the query. This will simplify the query plan, allowing you to inspect it. And may hopefully speed it up.
I note in your original query you are filtering you main table against #Start and #End in the join condition. I don't think you want to do that. I think it should be in the where clause.
Also you can probably pre-filter the temp table so long as you can work out which records may be required (I couldn't because you compare to 3 different dates).
DECLARE #start DATE = '7-1-2019', #end DATE = '8-20-2019';
-- Best practice is to list the actual columns required
-- You may also be able to pre-filter here based on #start and #end
-- But as you compare them to 3 different columns in the query I don't know enough about your logic to know if this is possible or not
-- You can also add indexes to the temp table if they would speed things up
select *
into #cg
from [CustSalesTrend_Growth];
SELECT cg.*
, ba.std_StandardAcctNo AS bonus_acct
FROM #cg cg
LEFT JOIN (
SELECT DISTINCT std_standardacctno
FROM #cg
WHERE eleph_Period_Date BETWEEN #Start AND #End
OR ideal_Period_Date BETWEEN #Start AND #End
) ba ON ba.std_StandardAcctNo = cg.std_StandardAcctNo
WHERE [Appearance_Count] <> 0
AND Period_gp <> 0
AND cg.Period_Date >= #Start
AND cg.Period_Date <= #End
ORDER BY cg.std_StandardAcctNo;
drop table #cg;
Try this query that uses CTEs. I do not have the schema so some of my assumptions may not be correct. Please verify the query before you execute.
WITH t1 AS
(
SELECT *
FROM CustSalesTrend_Growth
WHERE Appearance_Count <> 0
AND Period_gp <> 0
AND Period_Date between #Start and #End
),
t2 AS
(
SELECT DISTINCT std_StandardAcctNo
FROM CustSalesTrend_Growth
WHERE eleph_Period_Date BETWEEN #Start AND #End
OR ideal_Period_Date BETWEEN #Start AND #End
)
select t1.*, t2.std_StandardAcctNo AS bonus_acct
FROM t1
LEFT JOIN t2 ON t2.std_StandardAcctNo = t1.std_StandardAcctNo
ORDER BY t2.std_StandardAcctNo

MSSQL: calculate time be many starts and stops

Is it possible to make this in sql:
Have table with records:
ID LaborID OrderNr OrderStatusID OrderStatusDate
12990 3731573 OPT1814378 2 2018-05-28 09:35:30.123
13105 230687389 OPT1814378 1 2018-05-29 10:32:14.850
13106 230687389 OPT1814378 2 2018-05-29 10:52:14.403
13123 230480202 OPT1814378 1 2018-05-29 13:18:05.233
13130 230480202 OPT1814378 0 2018-05-29 13:29:17.360
12837 3731573 OPT1814089 2 2018-05-25 20:28:24.817
12906 10138504 OPT1814089 1 2018-05-26 10:41:18.680
12909 10138504 OPT1814089 2 2018-05-26 10:57:40.733
12913 10138504 OPT1814089 1 2018-05-26 11:41:48.387
12920 10138504 OPT1814089 0 2018-05-26 12:15:48.590
where
OrderStatusID
0 - End
1 - Begin
2 - pause
Need calculate working time from begin to pause (1->2) or from begin to end (1->0).
My problem is that there are some conditions that I have to adhere to:
If first record is 2 then ignore
Work begin always with 1
But can have more pause (1->2)
The last work end record everytime with 0
The result in this case will be:
OPT1814378 230687389 00:20:00
OPT1814378 230480202 00:11:12
OPT1814089 10138504 00:16:12
OPT1814089 10138504 00:34:00
Hopefully this is not that ugly.
; with
cte as
(
-- CTE for generating a sequence no
select *, rn = row_number() over (partition by OrderNr
order by OrderStatusDate)
from #table
),
cte2 as
(
-- Clean up invalid any rows and regenerate new sequence no
select ID, LaborID, OrderNr, OrderStatusID, OrderStatusDate,
rn = row_number() over (partition by OrderNr
order by OrderStatusDate)
from cte
where (rn = 1 and OrderStatusID = 1)
or rn >= 2
)
select OrderNr, LaborID,
convert(varchar(10),
dateadd(second,
datediff(second,
min(OrderStatusDate),
max(OrderStatusDate)),
0),
108)
from cte2
group by OrderNr,
LaborID,
(rn - 1) / 2
(rn - 1) / 2 will gives the value 0, 0, 1, 1, 2, 2 etc for grouping the rows two by two.
This one also works
;WITH CTE
AS (
SELECT row_number() OVER ( PARTITION BY ordernr ORDER BY id ) RN ,* FROM test_ti
)
,cte2
AS (
SELECT *
FROM cte c1
WHERE NOT EXISTS (
SELECT *
FROM cte c2
WHERE c1.id = c2.id
AND c2.rn = 1
AND c2.orderstatusid = 2
)
)
SELECT OrderNr
,LaborId
,TimeInterval
FROM ( SELECT DateDiff(MI, TIME, NxtTm) TimeInterval ,*
FROM (
SELECT * ,lead(TIME) OVER ( ORDER BY id ) NxtTm
FROM cte2
) x
WHERE orderstatusid <> 0
) y
WHERE orderstatusid = 1

writing a mathematical formula in sql

Using the following sql query :
Select count(*) as Totaladmit From v_dbPatientAdmissions where AdmitDate > '2017-01-01' and AdmitDate <'2017-12-30' and PatientType = 2
Select count(*) as TotalDischarge From v_dbPatientAdmissions where DischargeDate > '2017-01-01' and DischargeDate <'2017-012-30' and PatientType = 2
select count(*) as totalIP from v_dbPatientAdmissions where PatientType=2 and DischargeDate is null
select count (BedName) as Bedcount from V_Beds
We get the following output:
TotalAdmit
66668
TotalDischarge
6651
TotalIP
91
BedCount
174
I want to write a mathematical formula that does the following :
In order to crate a crystal report that returns only one value (Rate), also for the Totaladmit and TotalDischarge i want to apply a condition the excludes the records that shares the same AdmitDate and DischargeDate.
As you have different condition on your select, so common group by with WHERE will not work.
You can try like following. This will be the simplest solution.
SELECT ( ( TotalIp + Totaladmit - TotalDischarge ) / BedCount ) * 100 AS
[Output]
FROM (SELECT (SELECT Count(*)
From v_dbPatientAdmissions
where AdmitDate > '2017-01-01'
and AdmitDate < '2017-12-30'
and PatientType = 2) as Totaladmit,
(SELECT Count(*)
From v_dbPatientAdmissions
where DischargeDate > '2017-01-01'
and DischargeDate < '2017-12-30'
and PatientType = 2) as TotalDischarge,
(SELECT Count(*)
from v_dbPatientAdmissions
where PatientType = 2
and DischargeDate is null) as TotalIp,
(SELECT Count (BedName)
from V_Beds) AS Bedcount) T
Apart from this, you can also use CROSS APPLY for doing the same thing.
Please try this-
SELECT
( (
SUM(CASE WHEN PatientType=2 and DischargeDate is null THEN 1 ELSE 0 END) OVER()
+ SUM(CASE WHEN AdmitDate > '2017-01-01' and AdmitDate <'2017-12-30' and PatientType = 2 THEN 1 ELSE 0 END) OVER() )
- (SUM(CASE WHEN DischargeDate > '2017-01-01' and DischargeDate <'2017-012-30' and PatientType = 2 THEN 1 ELSE 0 END) OVER() )
) * 100.0 / ( select COUNT(BedName) OVER() from V_Beds )
FROM v_dbPatientAdmissions
I would bypass the complication of same day discharge by including them in the calculation
for example
drop table t
go
create table t(patientid int, admitdate date, dischargedate date)
create table b(bedname varchar(1))
go
truncate table t
insert into t values (1,'2017-01-01','2017-01-01'),(1,'2017-02-01',null),(2,'2017-01-01','2017-02-01'),
(3,'2016-01-01','2017-01-01'),(4,'2016-01-01',null)
insert into b values ('a'),('b')
select (admittednull + (admitted - discharged - sameday)) / beds * 100 as calulatedratio
from
(
select sum(case when year(admitdate) = 2017 then 1 else 0 end) as admitted,
sum(case when year(dischargedate) = 2017 then 1 else 0 end) as discharged,
sum(case when year(admitdate) <> 2017 and dischargedate is null then 1 else 0 end) as admittednull,
(select count(*) from b) beds,
sum(case when year(admitdate) = 2017 and year(dischargedate) = 2017 and admitdate = dischargedate then 1 else 0 end) sameday
from t
) s
As it happens this returns a value of 0.

Get currency exchange rate in SQL

Using SQL Server, I have...
AccDocumentItems Table:
SLId DL1Id DL2Id Debit Credit CurId ExchangeRate Cnt
------------------------------------------------------------------------------
S1 D1 D4 2000 0 1 1000 2
S1 D1 D4 0 6000 1 1500 4
S1 D1 D4 6000 0 1 1200 5
S2 D2 D4 4000 0 2 1000 4
S2 D2 D4 0 2000 2 1000 2
S2 D2 D4 3000 0 2 1500 2
I am trying to write a query in sql that group by CurId then substract Cnt column that has debit greater than 0 from Cnt Column that has Debit 0,for example row 1 to 3 has CurId 1 and row 1 has Debit greater than zero,then we have (2-4+5)=3 and row 4 to 6 has CurId 2 then we have (4-2+2)=4 finally I want sum of them 3*Last ExchangeRate in ExchangeRates Table, and 4*Last ExchangeRate in ExchangeRates Table, then sum of (3*Last ExchangeRate+4*Last ExchangeRate).
ExchangeRates Table:
CurrencyId EffectiveDate ExchangeRate
------------------------------------------------
1 2016-1-1 1000
2 2016-1-2 1200
2 2016-1-3 2000
1 2016-1-4 1500
result=(3*Last ExchangeRate+4*Last ExchangeRate)-((sum of Debit)-(sum
of Credit))
in this example Last ExchangeRate for CurrencyId 1 is 1500, and Last ExchangeRate for CurrencyId 2 is 2000 finally I want this result
result=(3*1500+4*2000)-(15000-8000)
This solution is based on your calculations and works only with 2 CurId's.
declare #cur_1 int = 1
declare #cur_2 int = 2
;with AccDocumentItems as (
select
*
from
(values
('S1','D1','D4',2000,0,1,1000,2)
,('S1','D1','D4',0,6000,1,1500,4)
,('S1','D1','D4',6000,0,1,1200,5)
,('S2','D2','D4',4000,0,2,1000,4)
,('S2','D2','D4',0,2000,2,1000,2)
,('S2','D2','D4',3000,0,2,1500,2)
) t (SLId, DL1Id, DL2Id, Debit, Credit, CurId, ExRate, Cnt)
)
, ExchangeRates as (
select
*
from
(values
(1,'2016-1-1',1000)
,(2,'2016-1-2',1200)
,(2,'2016-1-3',2000)
,(1,'2016-1-4',1500)
) t (CurrencyId, EffectiveDate, ParityRate)
)
select
sum(t.cnt * q.ParityRate) - sum(diff)
from
(
select
CurId, diff = sum(Debit) - sum(Credit), cnt = sum(cnt * case when Debit = 0 then -1 else 1 end)
from
AccDocumentItems
where
CurId in (#cur_1, #cur_2)
group by CurId
) t
join (
select
top 1 with ties *
from
ExchangeRates
order by row_number() over (partition by CurrencyId order by EffectiveDate desc)
) q on t.CurId = q.CurrencyId
This solution works for All CurId's.
Declare #Result int
Declare #DeCr int
Declare #Cur int
Set #DeCr = (
Select SUM(Debit)-SUM(Credit)
From dbo.AccDocumentItems
)
Set #Cur =
(
Select Sum(ParityRate * Zarib)
From
(
Select ExchangeRates.CurrencyId as cuur,ParityRate
From
(
Select Max(EffectiveDate) As MaxDate,CurrencyId
From dbo.ExchangeRates
Group by CurrencyId
)As Table1
left join
dbo.ExchangeRates
ON table1.currencyid = ExchangeRates.CurrencyId
And Table1.MaxDate = EffectiveDate
) As Table3
inner join
(
Select Curid
, sum(cnt*signs) As Zarib
From
(
Select CurId
, Cnt
, Case
When Debit = 0 Then -1
Else 1
End As Signs
From dbo.AccDocumentItems
) As Table2
Group by Curid
) As Table4
On Table3.cuur = Table4.Curid
)
Select #Cur - #DeCr
Declare #Result int
Declare #DeCr int
Declare #Cur int
Set #DeCr = (
Select SUM(Debit)-SUM(Credit)
From dbo.AccDocumentItems
)
Set #Cur =
(
Select Sum(ParityRate * Zarib)
From
(
Select ExchangeRates.CurrencyId as cuur,ParityRate
From
(
Select Max(EffectiveDate) As MaxDate,CurrencyId
From dbo.ExchangeRates
Group by CurrencyId
)As Table1
left join
dbo.ExchangeRates
ON table1.currencyid = ExchangeRates.CurrencyId
And Table1.MaxDate = EffectiveDate
) As Table3
inner join
(
Select Curid
, sum(cnt*signs) As Zarib
From
(
Select CurId
, Cnt
, Case
When Debit = 0 Then -1
Else 1
End As Signs
From dbo.AccDocumentItems
) As Table2
Group by Curid
) As Table4
On Table3.cuur = Table4.Curid
)
set #result = #Cur - #DeCr
Select #result

Better way than CTE

I've written a simple query, but I feel there should be a better way to do it. I'm essentially looking for a way to clean up this code to make it neater and more usable in the future. I will be using this in a few ssrs reports.
DECLARE #Month int = MONTH(GETDATE());
DECLARE #Year int = YEAR(GETDATE());
DECLARE #ThisMth DATE = DATEFROMPARTS(#Year,#Month,1);
DECLARE #BegYear DATE = DATEFROMPARTS(#Year, 7,1);
--EMPLOYEES
With EmpCount AS
(
SELECT
COUNT(DISTINCT(Employee)) As 'DistinctEmployees', PRCo
FROM
PREA
WHERE
Mth = #ThisMth
GROUP BY
PRCo),
TotalEmp AS
(
SELECT
COUNT(DISTINCT(Employee)) As 'TotalDistinctEmployees', PRCo
FROM
PREA
WHERE
Mth >= #BegYear
GROUP BY
PRCo),
Earnings AS
(
SELECT
SUM(Amount) AS Earnings, PRCo
FROM
PREA
WHERE
Mth = #ThisMth AND EDLType = 'E'
GROUP BY
PRCo),
TotalEarnings AS
(
SELECT
SUM(Amount) as TotalEarnings, PRCo
FROM
PREA
WHERE
Mth >= #BegYear and EDLType = 'E'
GROUP BY
PRCo),
Deductions AS
(
SELECT
SUM(Amount) AS Deduction, PRCo
FROM
PREA
WHERE
Mth = #ThisMth AND EDLType = 'D'
GROUP BY PRCo),
TotalDeduction AS
(
SELECT
SUM(Amount) as TotalDed, PRCo
FROM
PREA
WHERE
Mth >= #BegYear AND EDLType = 'D'
GROUP BY
PRCo),
Liabilities AS
(
SELECT
SUM(Amount) AS Liab, PRCo
FROM
PREA
WHERE
Mth = #ThisMth AND EDLType = 'L'
GROUP BY
PRCo),
TotalLiabilities AS
(
SELECT
SUM(Amount) as TotalLiab, PRCo
FROM
PREA
WHERE
Mth >= #BegYear AND EDLType = 'L'
GROUP BY
PRCo)
SELECT
a.PRCo, ec.DistinctEmployees, tem.TotalDistinctEmployees,
e.Earnings, te.TotalEarnings, d.Deduction, td.TotalDed,
l.Liab, tl.TotalLiab, te.TotalEarnings + tl.TotalLiab AS TotalCost
FROM
PREA a
INNER JOIN
EmpCount ec ON ec.PRCo = a.PRCo
INNER JOIN
Earnings e ON e.PRCo = a.PRCo
INNER JOIN
TotalEarnings te ON te.PRCo = a.PRCo
INNER JOIN
TotalEmp tem ON tem.PRCo = a.PRCo
INNER JOIN
Deductions d ON d.PRCo = a.PRCo
INNER JOIN
TotalDeduction td ON td.PRCo = a.PRCo
INNER JOIN
Liabilities l ON l.PRCo = a.PRCo
INNER JOIN
TotalLiabilities tl ON tl.PRCo =a.PRCo
WHERE
Mth = #ThisMth AND EDLType = 'E'
GROUP BY
a.PRCo, ec.DistinctEmployees,e.Earnings, te.TotalEarnings,
tem.TotalDistinctEmployees, d.Deduction, td.TotalDed, l.Liab, tl.TotalLiab
try this:
SELECT PRCo
,COUNT(DISTINCT(CASE WHEN Mth = #ThisMth THEN Employee ELSE NULL END )) As 'DistinctEmployees'
,COUNT(DISTINCT(CASE WHEN Mth >= #BegYear THEN Employee ELSE NULL END )) As 'TotalDistinctEmployees'
,SUM(CASE WHEN Mth = #ThisMth AND EDLType = 'E' THEN Amount ELSE 0 END ) AS Earnings
,SUM(CASE WHEN Mth >= #BegYear and EDLType = 'E' THEN Amount ELSE 0 END) AS TotalEarnings
,SUM(CASE WHEN Mth = #ThisMth AND EDLType = 'D' THEN Amount ELSE 0 END ) AS Deduction
,SUM(CASE WHEN Mth >= #BegYear and EDLType = 'D' THEN Amount ELSE 0 END ) AS TotalDed
,SUM(CASE WHEN Mth = #ThisMth AND EDLType = 'L' THEN Amount ELSE 0 END ) AS Liab
,SUM(CASE WHEN Mth >= #BegYear and EDLType = 'L' THEN Amount ELSE 0 END ) AS TotalLiab
,SUM(CASE WHEN Mth >= #BegYear and EDLType like '[EL]' THEN Amount ELSE 0 END) AS TotalCost
FROM PREA AS p
GROUP BY PRCo

Resources