GROUP BY is causing blank fields in results - sql

I am working on trying to fix a problem in the below code.
The first 3000 or so records for the ADJ_CARDHOLDER_ID column are coming up blank/empty when running the query.
All other columns seem to be populating correctly.
I believe this is being caused by the group by which is needed for the sum aggregate.
Is there another way I can go about this which prevents the ADJ_CARDHOLDER_ID column from coming up blank?
Select ADJ_CARDHOLDER_ID,
I_SERVICE_DT,
I_PRODUCT_I,
sum(Claim_Count) as 'Total Claim Count'
--into #temp_claims
from reporting.dbo.vcbt
where YEAR (I_SERVICE_DT) = Cast(Datepart(yyyy,GETDATE())as varchar(4))
and O_CLAIM_ITEM_RESP_STATUS_CD <> 'x'
and PLAN_ID not in('PH13-800W', 'PH13-OGBW', 'PH13-800WL', 'PH13-OGBWL', 'PH13-OGBWA', 'PH13-OGBWM', 'PH13-800WM', 'PH13-800WA')
Group by ADJ_CARDHOLDER_ID, I_PRODUCT_I, I_SERVICE_DT
order by ADJ_CARDHOLDER_ID, I_SERVICE_DT, I_PRODUCT_I

Related

Most recent transaction date against a Works Order?

Apologies in advance for what will probably be a very stupid question but I've been using Google to teach myself SQL after making the move from years of using Crystal Reports.
We have Works Orders which can have numerous transactions against them. I want to find the most recent one and have it returned against the Works Order number (which is a unique ID)? I attempted to use MAX but that just returns whatever the Transaction Date for that record is.
I think my struggles may be caused by a lack of understanding of grouping in SQL. In Crystal it was just 'choose what to group by' but for some reason in SQL I seem to be forced to group by all selected fields.
My ultimate goal is to be able to compare the planned end date of the Works Order ("we need to finish this job by then") vs when the last transaction was booked against the Works Order, so that I can create an OTIF KPI.
I've attached an image of what I'm currently seeing in SQL Server 2014 Management Studio and below is my attempt at the query.
SELECT wip.WO.WO_No
, wip.WO.WO_Type
, stock.Stock_Trans_Log.Part_No
, stock.Stock_Trans_Types.Description
, stock.Stock_Trans_Log.Qty_Change
, stock.Stock_Trans_Log.Trans_Date
, wip.WO.End_Date
, wip.WO.Qty - wip.WO.Qty_Stored AS 'Qty remaining'
, MAX(stock.Stock_Trans_Log.Trans_Date) AS 'Last Production Receipt'
FROM stock.Stock_Trans_Log
INNER JOIN production.Part
ON stock.Stock_Trans_Log.Part_No = production.Part.Part_No
INNER JOIN wip.WO
ON stock.Stock_Trans_Log.WO_No = wip.WO.WO_No
INNER JOIN stock.Stock_Trans_Types
ON stock.Stock_Trans_Log.Tran_Type = stock.Stock_Trans_Types.Type
WHERE (stock.Stock_Trans_Types.Type = 10)
AND (stock.Stock_Trans_Log.Store_Code <> 'BI')
GROUP BY wip.WO.WO_No
, wip.WO.WO_Type
, stock.Stock_Trans_Log.Part_No
, stock.Stock_Trans_Types.Description
, stock.Stock_Trans_Log.Qty_Change
, stock.Stock_Trans_Log.Trans_Date
, wip.WO.End_Date
, wip.WO.Qty - wip.WO.Qty_Stored
HAVING (stock.Stock_Trans_Log.Part_No BETWEEN N'2Z' AND N'9A')
Query + results
If my paraphrase is correct, you could use something along the following lines...
WITH
sequenced_filtered_stock_trans_log AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY WO_No
ORDER BY Trans_Date DESC) AS reversed_sequence_id
FROM
stock.Stock_Trans_Log
WHERE
Type = 10
AND Store_Code <> 'BI'
AND Part_No BETWEEN N'2Z' AND N'9A'
)
SELECT
<stuff>
FROM
sequenced_filtered_stock_trans_log AS stock_trans_log
INNER JOIN
<your joins>
WHERE
stock_trans_log.reversed_sequence_id = 1
First, this will apply the WHERE clause to filter the log table.
After the WHERE clause is applied, a sequence id is calculated. Restarting from one for each partition (each WO_No), and starting from the highest Trans_Date.
Finally, that can be used in your outer query with a WHERE clause that specifies that you only want the records with sequence id one, this it the most recent row per WO_No. The rest of the joins on to that table would proceed as normal.
If there is any other filtering that should be done (through joins or any other means) that should all be done before the application of the ROW_NUMBER().

Over By Partition Issues

I am having some issues with Over Partition by. I am trying to get:
Desired Result
The inventory ordered column is the problem using this code:
select
l.whseloc,l.invtid,
l.qty,
case when f.MRPFlag= 0 then 'NON-Usable' else 'Usable' end as NetStatus,
SUM(p.qtyord-p.qtyrcvd) over (Partition by l.invtid) as InventoryOrdered,
SUM(l.qty*f.mrpflag)over(partition by l.invtid) as TotalNet
from location l (nolock)
join inventory i (nolock) on l.invtid=i.invtid
join loctable f (nolock) on l.whseloc=f.whseloc
left join [dbo].[opspurord] p (nolock) on l.InvtID=p.InvtID
What am I doing wrong?
First Try
There is not enough information (no sample data) in the question to tell you where you have gone wrong, so I will describe how to debug and fix the problem.
Display PARTITION BY columns and aggregated columns in your result set as separate columns, while keeping everything else the same.
select l.whseloc, l.invtid, l.qty,
case when f.MRPFlag= 0 then 'NON-Usable' else 'Usable' end as NetStatus,
SUM(p.qtyord-p.qtyrcvd) over (Partition by l.invtid) as InventoryOrdered,
p.qtyord-p.qtyrcvd AS InventoryOrderedRowSUM
SUM(l.qty*f.mrpflag)over(partition by l.invtid) as TotalNet,
l.qty*f.mrpflag AS TotalNetRowSUM
from location l (nolock)
...
ORDER BY l.invtid -- Add Order BY to make it easier to analyse data
l.invtid - this will show you groups of rows which summed by SUM function
InventoryOrderedRowSUM - shows you the value produced for each row. If you manually add up these values for a given l.invtid you should get the same result as InventoryOrdered.
Where to go from here:
By looking at the individual InventoryOrderedRowSUM you should be able to tell what combination of these values gives you the desired result. Once you have this worked out, you can adjust your InventoryOrdered function. If this is not obvious, then you need repeat the above process while adding p.qtyord and p.qtyrcvd to the result set.
I suspect that InventoryOrdered should just be p.qtyord-p.qtyrcvd (no SUM needed) based on the fact that 11200 is divisible by 1600.

Get Next Value within Row Groups in SSRS

I have a problem I'm trying to solve with getting the NextRow value but only within the specific RowGroup.
Here's what I'm trying to do:
if Fields!Interventions.Value is not blank and nextrow(Fields!DateOccurred.Value) within the group is within 4 hours then Y else N
and another column:
if Fields!Interventions.Value is not blank compare currentrow(Fields!DateOccurred.Value) to nextrow(Fields!DateOccurred.Value) and display the differences in hours
But I'm stuck as to how i could do this expression from within SSRS.
I saw the following question:
Get previous,current and Next Record in ssrs report in a page
but the issue with this one is that it doesn't work with Row Groups in SSRS.
Upon further advise, it appears as this isn't possible to do in SSRS, but would be possible in the query itself.
This is the query I'm working with:
SELECT
ROW_NUMBER() OVER(PARTITION BY R.PatientID, PL.ChartLocationID ORDER BY P.DateOccurred ASC) As Row#,
R.NameFirst,
R.NameLast,
P.DateOccurred,
CASE P.Interventions
WHEN 1 Then 'Regular Analgesia'
When 2 Then 'Heat Pack'
When 4 Then 'Cold Pack'
When 8 Then 'Massage'
When 16 Then 'Exercise'
When 32 Then 'Other'
END as Interventions
FROM
ChartEntry P
LEFT JOIN ChartLocation PL on
P.ChartLocationId = PL.ChartLocationId
Inner Join Resident R on
PL.ResidentID = R.PatientID
where
P.DateDeleted is null and
P.DateOccurred >= '01 Jul 2017' and
P.DateOccurred < '01 Aug 2017'
Is it possible to achieve?
Here is some sample data showing the results for the extra two columns:
Easiest and better way is to use LAG/LEAD in your SQL to figure this out.
You can do this in SSRS:
Set your detail value to Previous(Fields!DateOccurred.Value) and the detail row visibility to = RowNumber("yourgroup") = 1 which will hide the first row.
Use one row on the group total, in order to display the last value by setting its value to =Last(Fields!DateOccurred.Value)
The date difference expression check for the detail will be
=Iif(
NOT(Fields!Interventions.Value Is Nothing) AND
DateDiff("h", Previous(Fields!DateOccurred.Value),Fields!DateOccurred.Value)>=4,
"Y",
"N"
)
and for the last line
=Iif(
NOT(Fields!Interventions.Value Is Nothing) AND
DateDiff("h", Last(Fields!DateOccurred.Value),Now())>=4,
"Y",
"N"
)
In the images below, the red line will be hidden with the visibility condition.
Your report will contain only the expected date column, I include the current row date for demonstration.

IBM DB2: Using MINUS to exclude information in the subselect statement

Currently I am having an issue bringing back the correct data for this particular query below. I am attempting to bring back data that excludes select criteria from the subselect statement after MINUS keyword.
SELECT
DISTINCT ORDER.OWNER, ORDER_H.PO_ID
FROM ORDER ORDER
WHERE ORDER.TYPE != 'X'
AND ORDER.STATUS='10'
AND ORDER.CLOSE_DATE IS NULL MINUS
(
SELECT
DISTINCT ORDER.OWNER, ORDER.PO_ID
FROM ORDER ORDER
INNER JOIN COST COST ON COST.PO_ID = ORDER.PO_ID
AND COST.CODE IN
(
'LGSF',
'DFCDC',
'BOF',
'TFR',
'RFR',
'TFLHC',
'BF',
'CBF',
'CHAP',
'DYPH' ,
'OFFP',
'PTWT',
'DTEN',
'OTHR',
'DMSG',
'STOR',
'TOF',
'ANTCV',
'ANTIP',
'CVD',
'TRAN'
)
WHERE ORDER.TYPE != 'OTR'
AND ORDER.STATUS = '10'
AND (COST.E_AMT > 0 AND COST.A_AMT IS NULL)
)
FOR READ ONLY WITH UR
The data coming back includes the data within the subquery instead of excluding this data from the resultset. I cannot figure out why this is the case. Does anyone have any idea why after MINUS it doesn't exclude this data and is bringing back data where COST.E_AMT is actually greater than 0 and COST.A_AMT is actually populated for each CODE listed in the subquery? Any help would be appreciated, thanks.

Access 2010 Find Most Recent Status via SQL

Need list of "ALL" document numbers (k002) with their the most recent maintenance date (lm01_s) and status_code. The code below finds last date from the entire table and any record with that date. This is not what I need. There is only one table. If I drop the status_code from the equation, this is easy.
SELECT k002, lm01_s, status_code
FROM stat_trans
WHERE (lm01_s = ANY (SELECT MAX(lm01_s) FROM stat_trans)) ORDER BY lm01_s;
I have also tried this ...
SELECT k002, lm01_s, advice_code
FROM romis_stat_trans
WHERE lm01_s IN (((SELECT Max(lm01_s) FROM romis_stat_trans GROUP BY k002)));
I have tried so many things that I forget what I have tried. Everything has been a dead end.
Use a subquery in the where clause to return only the records where lm01_s is equal to the max lm01_s. I found it's important to use a table alias or else Access will confuse the fields.
select k002,
lm01_s,
status_code
from stat_trans
where lm01_s=(select max(sc.lm01_s)
from stat_trans as sc
where sc.k002 = stat_trans.k002)