Exclude those orders which has service code 'AAAA' - sql

An order can have multiple services. As per the functionality, I have to remove those orders from the selection which have a service code 'AAAA'.
I mean if an order has two services code 'AAAA' and 'AAAB'. Then this must not be included in the output because this order has a Service code 'AAAA'. Please see the screenshot below for more info.
Query:
Select BO.OrderID ,OrderDate ,BackgroundServiceID , BST.BST_Name ,BST_Code from
BackgroundOrder BO
JOIN BackgroundOrderService BOS ON BO.OrderID = BOS.OrderID
JOIN ams.lkpBkgSvcType BST ON BST.BST_ID = BOS.BackgroundServiceID
Expected Output Query:
Select BO.OrderID ,OrderDate ,BackgroundServiceID , BST.BST_Name ,BST_Code from
BackgroundOrder BO
JOIN BackgroundOrderService BOS ON BO.OrderID = BOS.OrderID
JOIN ams.lkpBkgSvcType BST ON BST.BST_ID = BOS.BackgroundServiceID
Where BST.BST_Code = 'AAAB' AND BO.OrderID not in
(Select BO.OrderID from
BackgroundOrder BO
JOIN BackgroundOrderService BOS ON BO.OrderID = BOS.OrderID
JOIN ams.lkpBkgSvcType BST ON BST.BST_ID = BOS.BackgroundServiceID
Where BST.BST_Code = 'AAAA'
)
Please suggest some other ways to get the above output without using a not-in statement.

You can wrap your query in a cte and count the occurences of 'AAAA' per OrderId then filter where it's zero
with t as (
select BO.OrderID, OrderDate, BackgroundServiceID, BST.BST_Name, BST_Code,
Sum(case when bst_code='AAAA' then 1 else 0 end) over(partition by BO.OrderID) cnt=0
from BackgroundOrder BO
join BackgroundOrderService BOS on BOS.OrderID = BO.OrderID
join ams.lkpBkgSvcType BST on BST.BST_ID = BOS.BackgroundServiceID
)
select OrderID, OrderDate, BackgroundServiceID, BST_Name, BST_Code
from t
where cnt=0

Related

How to convert a query into a nested query

How do I change this query into a nested query?
The query and tables are listed below.
SELECT
Nation.N_NAME as "nation",
ROUND(
SUM(
Lineitem.L_QUANTITY * (Lineitem.L_EXTENDEDPRICE - Lineitem.L_DISCOUNT)
), 2
) AS "order size"
FROM Nation
JOIN Supplier ON Nation.N_NATIONKEY = Supplier.S_NATIONKEY
JOIN Customer ON Supplier.S_NATIONKEY = Customer.C_NATIONKEY
JOIN Orders ON Customer.C_CUSTKEY = Orders.O_CUSTKEY
JOIN Lineitem ON Orders.O_ORDERKEY = Lineitem.L_ORDERKEY
WHERE Lineitem.L_SUPPKEY = Supplier.S_SUPPKEY
GROUP BY Nation.N_NAME
;
tables goes as follows
Nation : N_NATIONKEY, N_NAME
Supplier : S_SUPPKEY, S_NAME, S_NATIONKEY
Customer : C_CUSTKEY, C_NAME, C_NATIONKEY
Orders: O_ORDERKEY, O_CUSTKEY
Lineitem: L_ORDERKEY, L_SUPPKEY, L_QUANTITY, L_EXTENDEDPRICE, L_DISCOUNT
I'm not sure exactly what kind of nested join you're looking for, but here is one option:
SELECT
src.N_NAME as "nation",
ROUND(
SUM(
lineitem.L_QUANTITY * (lineitem.L_EXTENDEDPRICE - lineitem.L_DISCOUNT)
), 2
) AS "order size"
FROM lineitem -- Get line items
INNER JOIN (
SELECT nation.N_NAME, supplier.S_SUPPKEY, Orders.O_ORDERKEY
FROM nation
JOIN Supplier ON Nation.N_NATIONKEY = Supplier.S_NATIONKEY
JOIN Customer ON Supplier.S_NATIONKEY = Customer.C_NATIONKEY
JOIN Orders ON Customer.C_CUSTKEY = Orders.O_CUSTKEY
) src ON lineitem.L_SUPPKEY = src.S_SUPPKEY AND lineitem.L_ORDERKEY = src.O_ORDERKEY
GROUP BY src.N_NAME
I haven't tested it but give it a try and see if it works. If it doesn't give you what you want, please post some sample data.

First event per patients

The attached code is supposed to return the first ORDER_PROC.ORDER_INST for each patient. I'm getting multiple records in some cases.
Any suggestions on a better approach?
Thanks
Steve
SELECT DISTINCT
ORDER_PROC.PAT_ENC_CSN_ID as ordercsn, Min(ORDER_PROC.ORDER_INST) as
CodeStatus_Datetime, CLARITY_SER.PROV_NAME as CodeStatus_OrderProvider
FROM
ORDER_PROC with(nolock) , ORDER_METRICS with(nolock) , CLARITY_SER
with(nolock)
WHERE
ORDER_PROC.ORDER_PROC_ID = ORDER_METRICS.ORDER_ID AND
ORDER_METRICS.ORDERING_PROV_ID = CLARITY_SER.PROV_ID AND
--ORDER_PROC.REASON_FOR_CANC_C IS NULL AND
(ORDER_PROC.PROC_CODE = 'COD1' OR
ORDER_PROC.PROC_CODE = 'COD2' OR
ORDER_PROC.PROC_CODE = 'COD3'
)
GROUP by
ORDER_PROC.PAT_ENC_CSN_ID, ORDER_PROC.ORDER_INST,CLARITY_SER.PROV_NAME
Use ROW_NUMBER() to create partition for each patient
SELECT *
FROM (
SELECT OP.PAT_ENC_CSN_ID as ordercsn,
OP.ORDER_INST,
CodeStatus_Datetime,
CS.PROV_NAME as CodeStatus_OrderProvider,
ROW_NUMBER() OVER (PARTITION BY OP.PAT_ENC_CSN_ID
ORDER BY OP.ORDER_INST) as rn
FROM ORDER_PROC OP
JOIN ORDER_METRICS OM
OP.ORDER_PROC_ID = OM.ORDER_ID
JOIN CLARITY_SER CS
OM.ORDERING_PROV_ID = CS.PROV_ID
WHERE
OP.PROC_CODE IN ('COD1','COD2','COD3')
) as T
WHERE rn = 1

SQL - Only show results for one column in first instance of a duplicated record

I am finding it difficult to explain exactly what I am trying to achieve so I think it best to show a visual representation.
Example of how my query results currently look
Example of how I want the results to look
The report I am running shows a list of every product within orders. Each product has its own cost assigned to it. Another column is a delivery charge, but this is a charge assigned to the order; not individual products. I want to be able to show the delivery charge against the first product in each order ONLY.
I have attempted, for far too long, to try and find an answer to this query but have had no luck. I don't know if it is even possible so assistance of any sort, or even just being pointed in the right direction, would be of great help.
Thanks
EDIT.
If it helps here is my query:
SELECT dbo.Orders.EncryptedOrderId,
dbo.OrderProduct.ProductID,
dbo.OrderProduct.QuantityPerRecipient,
dbo.OrderProduct.NumRecipients,
dbo.OrderProduct.TotalQuantity,
dbo.DocType.Name AS [Product Type],
dbo.ProductGroup_Culture.Name AS [Product Group],
RIGHT(CatalogNo, CHARINDEX('_', REVERSE('_' + CatalogNo)) -1) AS [HamptonsType],
FORMAT(dbo.Orders.DateOrderCreated, 'dd/MM/yyyy HH:mm:ss') AS 'DateOrderCreated',
CAST(REPLACE(dbo.Orders.ClearingResult, 'utf-8', 'utf-16') AS XML ).value('(/UserData//CostCenter/node())[1]', 'nvarchar(max)') AS [Cost Center],
dbo.Users.FirstName,
dbo.Users.LastName,
dbo.Users.CompanyName AS [Branch Name],
dbo.Users.Department AS Subsidiary,
dbo.Users.Custom1,
dbo.Users.Custom2,
dbo.Users.Custom3,
dbo.Users.Custom4,
dbo.Users.Custom5,
dbo.OrderProduct.TotalPrice,
dbo.Orders.ShippingCharges,
dbo.OrderProduct.OrderProductID,
dbo.FileSubmissionDocument.OriginalFileType,
COALESCE (dbo.FileSubmissionDocument.Title, dbo.Product_Culture.Name) AS [Product Name],
OPDV.FriendlyValue AS 'BCard Recipient'
FROM dbo.DocType
INNER JOIN dbo.Doc
ON dbo.DocType.DocTypeID = dbo.Doc.DocTypeID
INNER JOIN dbo.OrderProduct
ON dbo.Doc.ProductID = dbo.OrderProduct.ProductID
LEFT JOIN dbo.Product
ON dbo.Product.ProductID = dbo.Doc.ProductID
LEFT JOIN dbo.ProductGroupMembership
ON dbo.ProductGroupMembership.ProductID = dbo.Doc.ProductID
LEFT JOIN dbo.ProductGroup_Culture
ON dbo.ProductGroup_Culture.ProductGroupID = dbo.ProductGroupMembership.ProductGroupID
INNER JOIN dbo.Orders
ON dbo.OrderProduct.OrderID = dbo.Orders.OrderID
INNER JOIN dbo.Users
ON dbo.Orders.UserID = dbo.Users.UserID
INNER JOIN dbo.Product_Culture
ON dbo.OrderProduct.ProductID = dbo.Product_Culture.ProductID
INNER JOIN dbo.Store_Culture
ON dbo.Store_Culture.StoreID = dbo.Users.AssignedToStoreID FULL OUTER
JOIN dbo.FileSubmissionDocument
ON dbo.OrderProduct.OrderProductID = dbo.FileSubmissionDocument.SubOrderProductID - 1
LEFT JOIN (SELECT OP.OrderProductID,
OP.DialID,
OP.FriendlyValue
FROM OrderProductDialValue OP
LEFT JOIN Dial DI ON DI.DialID = OP.DialID
LEFT JOIN OrderProduct OT ON OT.OrderProductID = OP.OrderProductID
LEFT JOIN Product PR ON PR.ProductID = OT.ProductID
WHERE PR.ExternalID = 'BCName'
AND DI.UProduceDialName = 'Name') OPDV ON OPDV.OrderProductID = dbo.OrderProduct.OrderProductID
WHERE ('#CUSTOMERNAME' is null
OR '#CUSTOMERNAME' = ''
OR dbo.Store_Culture.Name LIKE '%' + '#CUSTOMERNAME' + '%')
AND dbo.OrderProduct.IsDraft = 0
AND dbo.Orders.IsCart=0
AND dbo.Orders.IsSaveForLater=0
AND (('#DATE' <= dbo.Orders.DateOrderCreated)
OR ('#DATE' IS NULL)
OR ('#DATE'=''))
AND ((DATEADD(day, 1, '#DATE') >= dbo.Orders.DateOrderCreated)
OR ('#DATE' IS NULL)
OR ('#DATE'=''))
AND dbo.Users.LastName NOT LIKE '%TEST%'
ORDER BY dbo.Orders.OrderID DESC, dbo.OrderProduct.OrderProductID DESC
The query runs through a reporting system on an online portal so the values that show as #CUSTOMERNAME or #DATE are variables based on values given at the time when the report is run.
this may help you
select orderid,
productid,
productvalue,
case ROW_NUMBER() over (partition by orderid order by orderid)
when 1 then deliverycharge
else null end as 'deliverycharge'
from ........
I assume your query looks like
select orderID
, productID
, productValue
, DeliveryCharge
from test_t
order by orderID
, productValue desc
;
and that you want delivery charges listed for the most expensive product of each order.
If supported by your rdbms, you can use the analytic RANK function
select orderID
, productID
, productValue
, DeliveryCharge
, CASE RANK() OVER ( PARTITION BY orderID ORDER BY productValue DESC ) WHEN 1 THEN DeliveryCharge ELSE NULL END r
from test_t
order by orderID
, productValue desc
;
If your rdbms does not support RANK, you can emulate it using a left join with a suitably aggregated copy of your table:
select t.orderID
, t.productID
, t.productValue
, rt.mdc DeliveryCharge
from test_t t
left join (
select orderID
, max(productValue) mp
, max(DeliveryCharge) mdc
from test_t
group by orderID
) rt
on (
rt.orderID = t.orderID
AND rt.mp = t.productValue
)
order by orderID
, productValue desc
;
The tacit assumption is that the delivery charge is by order (which seems reasonable as you wouldn't want to selectively drop it otherwise, right ?).
Moreover, both solutions will produce multiple rows containing the delivery charge per order if that order contains multipleproducts with the same productValue.
Tested on oracle 12c1;

Major issues with a query

I have a query
SELECT
ZEML.ICC_CODE AS ICC_CODE
,SUM(CS.TOT_HOURS) AS TOT_HOURS
,SUM(CS.NUM_INCIDENT_ALL) AS NUM_INCIDENTS
,(VALUE(FLOAT(SUM(CS.NUM_INCIDENT_ALL)) * 200000 / SUM(TOT_HOURS)
,0)) AS INC_RATE
FROM TR.CLAIMS_SUMM CS
INNER JOIN TR.LOCATION_MASTER LM
ON LM.LOCATION = CS.LOCATION
AND CS.LOCATION < '900'
LEFT JOIN TR.LOCATION_ASSIGNMENTS DISTRICT
ON DISTRICT.LOCATION = LM.LOCATION
AND DISTRICT.ASSIGNMENT_TYPE = 'District'
LEFT JOIN TR.LOCATION_ASSIGNMENTS TERRITORY
ON TERRITORY.LOCATION = LM.LOCATION
AND TERRITORY.ASSIGNMENT_TYPE = 'Territory'
LEFT JOIN TR.EMPL_CLAIMS ZEML
ON CS.LOCATION = ZEML.LOCATION
AND ZEML.TYPE = 'WC'
AND ZEML.STATUS <> 'V'
AND ZEML.CLAIM_ACTION NOT IN ('D','F','I','H')
WHERE CS.DW_DATE BETWEEN '01/01/2014'
AND '05/31/2014'
AND (MONTH(ZEML.DATE_OF_INCIDENT) = MONTH(CS.DW_DATE)
AND YEAR(ZEML.DATE_OF_INCIDENT) = YEAR(CS.DW_DATE))
GROUP BY ZEML.ICC_CODE
UNION
SELECT
'OTHER' AS ICC_CODE
, 0 AS TOT_HOURS
, 0 AS NUM_INCIDENTS
, 0 AS INC_RATE
FROM SYSIBM.SYSDUMMY1
WHERE 1 = 1
ORDER BY 1
in my union where I made an other I want to select everything else from the tr.empl_claims table and store it in the other from the union because this is what I have many other ICC codes without incidents on them and I am doing calculations on our incident rate and hourse based off of all the data but my query right now is only selecting the ones that currently is having incidents which is throwing off my calculations.
From your use of FROM SYSIBM.SYSDUMMY1 I believe you are using DB2 database. If yes, you can use CTE (common table expression) to achieve the desired result like
WITH cte1 AS
(
SELECT
ZEML.ICC_CODE AS ICC_CODE
,SUM(CS.TOT_HOURS) AS TOT_HOURS
,SUM(CS.NUM_INCIDENT_ALL) AS NUM_INCIDENTS
,(VALUE(FLOAT(SUM(CS.NUM_INCIDENT_ALL)) * 200000 / SUM(TOT_HOURS)
,0)) AS INC_RATE
FROM TR.CLAIMS_SUMM CS
... <rest of the code> ...
)
select * from cte1
UNION ALL
SELECT
ICC_CODE
, 0 AS TOT_HOURS
, 0 AS NUM_INCIDENTS
, 0 AS INC_RATE
FROM TR.EMPL_CLAIMS
WHERE ICC_CODE NOT IN
(
SELECT distinct ICC_CODE
FROM cte1
)
ORDER BY 1
SideNote: You are joining the same table LOCATION_ASSIGNMENTS twice (as below) which is not needed.
LEFT JOIN TR.LOCATION_ASSIGNMENTS DISTRICT
ON DISTRICT.LOCATION = LM.LOCATION
AND DISTRICT.ASSIGNMENT_TYPE = 'District'
LEFT JOIN TR.LOCATION_ASSIGNMENTS TERRITORY
ON TERRITORY.LOCATION = LM.LOCATION
AND TERRITORY.ASSIGNMENT_TYPE = 'Territory'
This can be transformed to below using a IN operator
LEFT JOIN TR.LOCATION_ASSIGNMENTS DISTRICT
ON DISTRICT.LOCATION = LM.LOCATION
AND DISTRICT.ASSIGNMENT_TYPE IN ('District', 'Territory')
See more about Common Table Expression in DB2 Here.
Hope this helps.

Distinct, count, group by query madness

I am trying to return a count of tests taken per term. I can get the count to return, but I can't get it grouped by term.
I've tried everything and the closest I get is grouping by term but then my count only = 1, which isn't right.
Here is what I have now. It just returns a count, how do I group it by term_id?
SELECT COUNT(*)
FROM (SELECT DISTINCT ON(student_id, test_event_id, terf.term_id) student_id
FROM report.test_event_result_fact terf
JOIN report.growth_measurement_window gw on gw.term_id = terf.term_id
JOIN report.term t on t.term_id = terf.term_id
JOIN report.test tt on tt.test_id = terf.test_id
WHERE terf.partner_id = 98
AND growth_event_yn = 't'
AND gw.test_window_complete_yn = 't'
AND gw.growth_window_type = 'DISTRICT'
AND tt.test_type_description = 'SURVEY_WITH_GOALS') as TestEvents
Without knowing more about your setup, that's my best bet:
select term_id, count(*) AS count_per_term
from (
select Distinct on (student_id, test_event_id, terf.term_id)
terf.term_id, student_id
from report.test_event_result_fact terf
join report.growth_measurement_window gw using (term_id)
join report.term t using (term_id)
join report.test tt using (term_id)
where terf.partner_id = 98
and growth_event_yn = 't'
and gw.test_window_complete_yn = 't'
and gw.growth_window_type = 'DISTRICT'
and tt.test_type_description = 'SURVEY_WITH_GOALS') as TestEvents
group by 1;