I have a view which has
ID INQCLASS INQDETAIL Period BAL
1233 GROSS water 12-3-2017 233.32
1233 GROSS ENergy 12-3-2017 122.00
ID,INQCLASS, Period is same. Except the INQDETAIL and BAL
I want to combine this into a single row which displays water and energy Bal.
Any Suggestions would be helpful. Thank you
SELECT ID,
INQCLASS,
Period,
MAX(CASE WHEN INQDETAIL = 'water' then BAL else 0 end) as WaterBal,
MAX(CASE WHEN INQDETAIL = 'ENergy' then BAL else 0 end) as ENergyBal
FROM View_Name
GROUP BY ID, INQLASS, Period
The case statement serves to show the BAL only when the condition is met. So with case alone, this would still return two rows for each item, but one would have a Waterbal value and no energybal value, and the other would be the reverse.
When you do GROUP BY, every field has to either be in the GROUP BY list (in this case, ID, INQCLASS, Period), or have an aggregate function like SUM, MAX, COUNT, etc. (in this case Waterbal and energyBal have aggregate functions).
The GROUP BY in this case collapses the common ID, INQLASS, Period into single rows, and then takes the largest (MAX) value for Waterbal and energyBal. Since one is always 0, it simply supplies the other one.
A simple pivot table ought to do it. As long as you know Inqdetail values ahead of time:
select ID,
INQCLASS,
[Period],
[Water] AS [Water Bal],
[Energy] as [Energy Bal]
from
(
select [ID],
[INQCLASS],
[INQDETAIL],
[Period],
[BAL]
from #util
) As Utilities
PIVOT
(
SUM([BAL])
FOR [inqdetail] IN ([Water],[Energy])
) AS Pvttbl
Try something like this:
SELECT INQDETAIL
, PERIOD
, SUM(BAL) AS energy_Bal
FROM your_view
WHERE INQDETAIL LIKE 'water'
GROUP BY INQDETAIL
, PERIOD;
Try this:
SELECT *
FROM
(SELECT * FROM #temp) AS P
PIVOT
(
max(bal) FOR INQDETAIL IN ([water], [ENergy])
) AS pv1
Related
I am trying to get my surgeries to calculate at different rates and I am struggling with it. For example, patient 58903 has 4 total surgeries as shown below. However, I would like the first surgery to calculate at 100% of the PPO SURG rate (so $4232), the second one at 50%, and all remaining surgeries at 25% of the main PPO SURG rate. My current code returns $16,929 for patient 5903 which is just $4232*4. My desired output for the SURG Total below is $8,464 (4232+2116+1058+1058).
My Current Code:
SELECT
DISTINCT PATNO,
SUM( PPOSURG) AS 'Surg Total',
SUM( PPONONSURG) AS 'Non Surg Total',
SUM( PPODRUG) AS 'Drug Total',
INSNME,
IIF( SUM( PPOSURG) IS NOT NULL,
SUM( PPOSURG) + SUM(CASE WHEN REV=278 THEN (AMT1)*0.446 END),
ISNULL(SUM( PPODRUG),0)+ISNULL( SUM( PPONONSURG),0)) AS 'Claim Total'
FROM
[OPGRACE$] AS GR --Main Table
LEFT JOIN [BCSURGOP$] AS SRG ON GR.CPTCDA=SRG.[CPTCODESURG] --SURG joined on cpt
LEFT JOIN [BCBSDRUG$] AS DRUG ON GR.CPTCDA=DRUG.[CPT CODE] --DRUG Schedules joined on cpt
LEFT JOIN [BCBSNONSURGOP$] AS NSRG ON GR.CPTCDA=NSRG.[CPT CODE] --Non-SURG joined on cpt
WHERE QTY>0 AND PATNO>0
GROUP BY PATNO,INSNME
ORDER BY PATNO ASC
I tried doing something like this but you can't have an aggregate in a SUM
SUM(CASE WHEN COUNT(CPTCODESURG)=1 THEN PPOSURG ELSE PPOSURG*0.5 END) + SUM(CASE WHEN REV=278 THEN (AMT1)*0.446 END),
Here is my output for just patient 58903
SURG Total
Non Surg Total
Drug Total
CLAIM Total
16929.472
3103
179
22598.84
Here is a blurb of my joined table showing how patient 58903 shows up:
PName
Rev
CPT
PPOSURG
58903
360
29882
4232.368
58903
360
29882
4232.368
58903
360
29882
4232.368
58903
360
29882
4232.368
Would a PARTITION be the way to go here? A subquery? Can I somehow use a case statement? I don't expect anyone to write my code but literally any ideas would be extremely helpful, I have been really stuck on this.
If I understand you correctly you just need a row number partitioned by the patient and then a CASE expression to convert that into a multiplier. I've added an id column to the sample data to allow for an order by (which you need for a row number).
declare #Test table (id int identity(1,1), PName int, Rev int, CPT int, PPOSURG money);
insert into #Test (PName, Rev, CPT, PPOSURG)
values
(58903, 360, 29882, 4232.368),
(58903, 360, 29882, 4232.368),
(58903, 360, 29882, 4232.368),
(58903, 360, 29882, 4232.368);
with cte as (
select *
, row_number() over (partition by PName order by id) rn
from #Test
)
select PName, Rev, CPT
, cast(sum(PPOSURG * case rn when 1 then 1.00 when 2 then 0.50 else 0.25 end) as decimal(9,2)) Total
from cte
group by PName, Rev, CPT;
I'm using T-SQL 2014
Suppose I have a stock price chart as follow
I want to write efficient code for a stored function to display the Open price at the start, Close price at the end, and the difference between Close and Open. Is it possible to do that in one query? The query seems easy but it turned out extremely difficult. My first problem is to display the first row and last row in one query.
My attempt is like this
create function GetVolatilityRank(#from date, #to date)
returns table as
return(
with Price_Selected_Time as (select * from Price where [date] between #from and #to)
select
(select top 1([Open]) from Price_Selected_Time) as 'Open',
(select top 1([Close]) from Price_Selected_Time order by date desc) as 'Close',
[Close] - [Open] as 'Difference'
);
I feel this code is very clumsy. And it also won't let me pass, because the 'Open'and 'Close' is not defined yet.
Is there anyway to query this in one select?
Thank you
We can handle this via a regular query using ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Date) rn_start,
ROW_NUMBER() OVER (ORDER BY Date DESC) rn_end
FROM Price
)
SELECT
MAX(CASE WHEN rn_start = 1 THEN [Open] END) AS OpenStart,
MAX(CASE WHEN rn_end = 1 THEN [Close] END) AS CloseEnd,
MAX(CASE WHEN rn_end = 1 THEN [Close] END) -
MAX(CASE WHEN rn_start = 1 THEN [Open] END) AS diff
FROM cte;
I have a table that stores the VIN numbers and delivery dates of vehicles based on a code. I want to be able to get one row with three columns of data.
I have tried the following
SELECT DISTINCT VIN, MAX(TRANSACTION_DATE) AS DELIVERY_DATE
FROM "TABLE"
WHERE DELIVERY_TYPE ='025'
AND VIN IN ('XYZ')
GROUP BY VIN
UNION ALL
SELECT VIN, MAX(TRANSACTION_DATE) AS OTHER_DELIVERY_DATE
FROM "TABLE"
WHERE DELIVERY_TYPE !='025'
AND VIN IN ('XYZ')
GROUP BY VIN;
When I run this I get
VIN DELIVERY_DATE
XYZ 26-dec-18
XYZ 01-MAY-19
current data format in table:
VIN TRANSACTION_DATE
XYZ 26-DEC-18
XYZ 01-MAY-19
Required format:
VIN DELIVERY_DATE OTHER_DELIVERY DATE
XYZ 26-DEC-18 01-MAY-19
use conditional aggregation
SELECT VIN,
MAX (CASE WHEN DELIVERY_TYPE ='025' AND
VIN IN ('XYZ') then TRANSACTION_DATE end) AS DELIVERY_DATE
MAX(CASE WHEN DELIVERY_TYPE !='025' AND
VIN IN ('XYZ') then TRANSACTION_DATE end) AS OTHER_DELIVERY
FROM "TABLE"
GROUP BY VIN
Just use conditional aggregation:
SELECT VIN,
MAX(CASE WHEN DELIVERY_TYPE = 25 THEN TRANSACTION_DATE END) AS DELIVERY_DATE,
MAX(CASE WHEN DELIVERY_TYPE <> 25 THEN TRANSACTION_DATE END) AS TRANSACTION_DATE
FROM TABLE
WHERE VIN IN ('XYZ')
GROUP BY VIN;
Note that SELECT DISTINCT is almost never used with GROUP BY.
You can use CROSS APPLY
DECLARE #Cars TABLE (VIN VARCHAR(100), DELIVERY_TYPE VARCHAR(3), TRANSACTION_DATE DATE)
INSERT INTO #Cars
(VIN, DELIVERY_TYPE , TRANSACTION_DATE)
VALUES
('XYZ', '025', '20181226'), ('XYZ', '030', '20190319')
I needed above code to be able to run without a table and data, all you need is this:
SELECT DISTINCT C.VIN, DD.DELIVERY_DATE, TD.TRANSACTION_DATE
FROM #Cars C
CROSS APPLY (SELECT MAX(TRANSACTION_DATE) DELIVERY_DATE FROM #Cars D WHERE D.DELIVERY_TYPE = '025' AND D.VIN = C.VIN) DD
CROSS APPLY (SELECT MAX(TRANSACTION_DATE) TRANSACTION_DATE FROM #Cars D WHERE D.DELIVERY_TYPE = '025' AND D.VIN = C.VIN) TD
If you need to transpond not two but a lot more columns, I'd suggest using PIVOT TABLE as more appropriate, but for two columns either CROSS APPLY or conditional aggregation will do the trick.
I use SqlExpress
Following is the query using which I get the attached result.
SELECT ReceiptId, Date, Amount, Fine, [Transaction]
FROM (
SELECT ReceiptId, Date, Amount, 'DR' AS [Transaction]
FROM ReceiptCRDR
WHERE (Amount > 0)
UNION ALL
SELECT ReceiptId, Date, Amount, 'CR' AS [Transaction]
FROM ReceiptCR
WHERE (Amount > 0)
UNION ALL
SELECT strInvoiceNo AS ReceiptId, CONVERT(datetime, dtInvoiceDt, 103) AS Date, floatTotal AS Amount, 'DR' AS [Transaction]
FROM tblSellDetails
) AS t
ORDER BY Date
Result
want a new column which would show balance amount.
For example. 1 Row should show -2500, 2nd should -3900, 3rd should -700 and so on.
basically, it requires previous row' Account column's data and carry out calculation based on transaction type.
Sample Result
Well, that looks like SQL-Server , if you are using 2012+ , then use SUM() OVER() :
SELECT t.*,
SUM(CASE WHEN t.transactionType = 'DR'
THEN t.amount*-1
ELSE t.amount END)
OVER(PARTITION BY t.date ORDER BY t.receiptId,t.TransactionType DESC) as Cumulative_Col
FROM (YourQuery Here) t
This will SUM the value when its CR and the value*-1 when its DR
Right now I grouped by date, meaning each day will recalculate this column, if you want it for all time, replace the OVER() with this:
OVER(ORDER BY t.date,t.receiptId,t.TransactionType DESC) as Cumulative_Col
Also, I didn't understand why in the same date, for the same ReceiptId DR is calculated before CR , I've add it to the order by but if thats not what you want then explain the logic better.
I want to use SUM() function on 'Amount' field in a query 4 times on a same field with different filters.
something like
SELECT Date1,CC,BU, SUM(Amount),SUM(Amount),SUM(Amount),SUM(Amount)
FROM MainTable<br>
GROUP BY CC,BU,Date1
Here
1st SUM(Amount) should be calculated when Mode='011' And Mode='012' from MainTable
2nd SUM(Amount) should be calculated when Mode like '03_' And Mode Like '05_' from MainTable
3rd SUM(Amount) should be calculated when Mode like '10_' from MainTable
4th SUM(Amount) should be calculated when (Mode !='011') and (Mode !='012') (Mode not Like '03_') and (Mode not Like '05_') from MainTable
How to make this happen? I have tried in many ways but couldn't get the result the way I wanted.
Please help me.
Thank you in advance.
You can use an aggregate function with a CASE:
SELECT Date1,
CC,
BU,
SUM(case when mode = '011' then Amount end) Mode011,
SUM(case when mode = '012' then Amount end) Mode012,
SUM(case when mode = '013' then Amount end) Mode013,
SUM(case when mode = '014' then Amount end) Mode014
FROM MainTable
GROUP BY CC,BU,Date1;
Or you can use the PIVOT function:
select date1, CC, BU,
[011] Mode011,
[012] Mode012,
[013] Mode013,
[014] Mode014
from
(
select date1, CC, BU, mode, amount
from maintable
) src
pivot
(
sum(amount)
for mode in ([011], [012], [013], [014])
) piv