SQL Server partition unnormalized data - sql-server

I think there might be a way to partition this to find what I want, but I can't see it. I have some slightly unnormalized data about product sets:
SetItemID ComponentItemID quantity IsPrimary
123 234 1 1
123 345 2 0
456 567 3 1
456 678 2 0
I need to find sets where the quantity's described are, for example, IsPrimary component's quantity > 'IsPrimary=0component'squantity. I also need to find sets where quantities are equal between components, etc. It's ok to use multiple statements for this, if necessary
All I have so far is a partial PARTITION statement that may or may not be the right way to do this, but I can't figure out how to compare quantities within sets:
WITH setdata as
(select *, row_number() OVER(
PARTITION by s.setitemid order by s.setitemid) position from set_table s )
// descending just to get newer sets
SELECT* from setdata order by setitemid desc

If I'm following your requirements right, this should do it:
SELECT p1.SetItemId
from (-- IsPrimary = 1
select SetItemID, ComponentItemId, Quantity
from SetData
where IsPrimary = 1) p1
inner join (-- IsPrimary = 0
select SetItemID, ComponentItemId, Quantity
from SetData
where IsPrimary = 0) p0
on p0.SetItemID = p1.SetItemID
and p1.Quantity > p0.Quantity
--and p1.Quantity = p0.Quantity
Use that last line for sets with equal quantities.

SELECT *
FROM set_table a
WHERE isPrimary = 1
AND quantity > (SELECT quantity
FROM set_table b
WHERE a.setItemId = b.setItemId
AND isPrimary = 0)
ORDER BY setItemId DESC
Or
SELECT a.*
FROM set_table a
INNER JOIN set_table b
ON a.setItemId = b.setItemId
AND a.isPrimary = 1
AND b.isPrimary = 0
WHERE a.quantity > b.quantity

Related

SQL query to bring back all orders only if all order details are in a list

I have an orders table that contains a lot of order specific info that is irrelevant to the question. However, I then have an orderDetails table that has a foreign key (orders.id == orderDetails.orderId). In this orderDetails, a customer can select to order lots of flavors of a product, each flavor gets a new entry in this table linked back to the main order.
What I want to do is select all the orders where ALL the flavors are present in the order. So, if an order has apple, peach and orange and I query for apple and peach, it wouldn't return that order because orange wasn't in my query.
I have tried subqueries and so on, but I feel like the only way to solve it is with looping each order and looking at the details, but that is horribly inefficient. Any thoughts?
SELECT *
FROM orders
WHERE id IN (SELECT orderId
FROM orderdetails
WHERE flavor IN('apple', 'peach', 'orange'))
AND isInvoiced = 1
AND isShipped = 0
AND isOnHold = 0
So, if I don't have any peach in stock, I want to see orders that do not contain any peach:
SELECT *
FROM orders
WHERE id IN (SELECT orderId
FROM orderdetails
WHERE flavor IN ('apple', 'orange'))
AND isInvoiced = 1
AND isShipped = 0
AND isOnHold = 0
The problem with the existing query here is that it returns everything because it just says, sure, you asked for apple... sure you asked for orange and this order contains those so I will return it. I need it to be ALL or nothing.
In the real database, the flavors are ID's, I just simplified it for this example.
Database tables were requested... I'll go ahead and list them as they really exist.
orders
-------
id
isInvoiced
isShipped
isOnHold
orderDetails
------------
id
orderId
flavorId
One more edit, this is my original failed attempt:
select * from orders WHERE id in
(
select orderId from orderdetails where flavorId in
(
'616a6d8e-be2e-4740-820b-1cad2a3d89b5',
'5d02f25b-f717-4079-97af-8aa444fe26b1',
'3504be8b-bebe-4b69-a22f-724d90003f99',
'c0a5a036-6dbe-417d-afcf-644f5520f2a8',
'29bfdea5-f270-44f0-9f48-245992af8401',
'29e53a21-4fdc-40e7-8bd9-733058a48097',
'60a90505-b9f5-4a60-8444-a35c2477d4a5',
'c9b93e89-98b0-4765-aedf-3a5f9d182c77',
'651ea709-a885-4f12-ad53-3290e8f0b18f',
'c5962375-d4d5-4ec7-82c0-0293475e6204',
'7faeffc0-fa88-4904-a6a9-7201949b23fd',
'24979b0d-7200-4a7d-9271-d26912d1b16d',
'5efeb81a-7642-4484-b8fc-62544bc8bff7'
)
)
and isInvoiced = 1 and isShipped = 0 and isOnHold = 0
That list of ID's would change based on what flavors are actually in stock.
basically you can just GROUP BY flavor with condition HAVING COUNT(*) = 3. So orders with those 3 flavor will be listed
select *
from orders o
where exists
(
select x.flavor
from orderdetails x
where x.orderId = o.id
and x.flavor in ('apple', 'peach', 'orange')
group by x.flavor
having count(*) = 3
)
and isInvoiced = 1
and isShipped = 0
and isOnHold = 0
You can use count function to make sure all flavors are represented.
select o.*
from orders o
inner join
(
select orderId, count(*) as flavorCount
from orderdetails
where flavor in ('apple', 'peach', 'orange')
group by orderId
) as t1
on o.orderId = t1.orderId
and isInvoiced = 1
and isShipped = 0
and isOnHold = 0
and t1.falvourCount = 3;
It would be simpler if you have a list of out-of-stock and in-stock flavors.
So if for example 'peach' is out of stock , and 'apple' and 'orange' are in stock, the following query will produce Orders that have only 'apple' OR 'orange' :
SELECT * FROM orders
WHERE
id IN (SELECT id FROM orderdetails WHERE flavor IN ('apple','orange') ) -- in stock
AND
id NOT IN (SELECT id FROM orderdetails WHERE flavor IN ('peach') ) --out of stock
What do you think ?
The question completely changed via this comment "I realize now I left out one very important part in that each order may have 1 or any number of flavors, not all have to be present."
The following query meets the original requirements: "What I want to do is select all the orders where ALL the flavors are present in the order" & "I need it to be ALL or nothing."
An order might have more than one item referring to a flavor ("apple pie", and "apple cake" for example), so I recommend you use 3 case expressions in a having clause to guard against this, whilst still achieving your objective:
select o.*
from orders as o
inner join (
select orderId
from orderdetails
group by orderId
having sum(case when flavor = 'apple' then 1 else 0 end) > 0
and sum(case when flavor = 'peach' then 1 else 0 end) > 0
and sum(case when flavor = 'orange' then 1 else 0 end) > 0
) as od on o.id = od.orderid
where o.isInvoiced = 1
and o.isShipped = 0
and o.isOnHold = 0
Note that the use of an inner join limits the orders listed to only those that refer to all 3 flavors.
This query is demonstrated here: http://rextester.com/AKMM54555

select distinct with parent-child and return boolean for at least one child with a value?

I am currently searching for orders that have at least one orderline (product) with a certain boolean set:
- the product is a subscription product
- the product is a setup product
If one of the orderlines has this value set to 1, I want to return this in the query per DISTINCT order ID.
This does not seem to work for me:
SELECT DISTINCT [ORDER].[order_id]
,[ORDERLINE].[is_subscription] AS hasSubArticles
,[ORDERLINE].[is_setup] AS hasSetupArticles
FROM [ORDER]
LEFT JOIN [ORDERLINE]
ON [ORDER].[order_id] = [ORDERLINE].[f_order_id]
WHERE [G_ORDER].[status] = 1
ORDER BY [ORDER].[order_id]
,[ORDERLINE].[is_subscription] AS hasSubArticles
,[ORDERLINE].[is_setup] AS hasSetupArticles
When I check the returned records, I receive duplicate ORDER records:
order_id hasSubArticles hasSetupArticles
----------------------------------------
17804 NULL NULL
17804 1 0
I want to return only 1 record per order ID, thus this isn't working for me.
What am I doing wrong?
Distinct does not work for your requirement. MAX, Min functions are not allowed to use with bit type. You could use Group by and SUM like this
SELECT
[ORDER].[order_id]
,CASE WHEN SUM( CASE WHEN [ORDERLINE].[is_subscription] = 1 THEN 1 ELSE 0 END) > 0 THEN 1
ELSE 0
END AS hasSubArticles
,CASE WHEN SUM( CASE WHEN [ORDERLINE].[is_setup] = 1 THEN 1 ELSE 0 END) > 0
THEN 1
ELSE 0
END hasSetupArticles
FROM [ORDER]
LEFT JOIN [ORDERLINE]
ON [ORDER].[order_id] = [ORDERLINE].[f_order_id]
WHERE [G_ORDER].[status] = 1
GROUP BY [ORDER].[order_id]

SQL Server - Struggling to group/sum values across multiple related tables

I'm running this query:
SELECT
g.PartNum,
g.Supplier,
(g.InitialQuantityToInventory + SUM(COALESCE(t.AmountInventoryAdjusted + t.AmountReturned, 0))) AS StockLevel
FROM
GoodsIn g
LEFT JOIN
Transfers t ON g.GoodsInNumber = t.GoodsInNumber
WHERE
g.PartNum = '123'
GROUP BY
g.PartNum, g.Supplier, g.InitialQuantityToInventory
And it's returns these results:
123,SUP1,67
123,NULL,18
123,NULL,0
123,NULL,45
123,NULL,0
However I would like the StockLevel (in the 3rd column) to SUM on the supplier name, even when it's null, so that my expected result should be:
123,SUP1,67
123,NULL,63
What am I doing wrong? The query should (across all GoodsIn Numbers that have the same PartNumber & Supplier) Sum the InitialQuantities and their Amounts Adjusted & Returned for each transfer associated with the GoodsIn record.
This is the data for that part & supplier in the GoodsIn Table:
GINum Part Num Supplier InitialQuantityToInventory
73367 123 NULL 81
73570 123 NULL 18
74154 123 NULL 320
74835 123 Sup1 0
74836 123 NULL 500
75738 123 Sup1 0
And this is the corresponding rows from the Transfers table (T being short for TransferNum):
GINum T Adj Ret
73367 1 -81 0
74154 1 -200 0
74154 2 -120 45
74835 1 67 0
74836 1 -500 0
75738 1 -300 0
75738 2 300 0
Do you need to not group by InitialQuantityToInventory?
;WITH Logs (Supplier, Initial, StockChange)
AS
(
SELECT
g.Supplier,
g.InitialQuantityToInventory,
(SUM(COALESCE(t.AmountInventoryAdjusted + t.AmountReturned,0))) AS StockChange
FROM
GoodsIn g
LEFT JOIN
Transfers t ON g.GoodsInNumber = t.GoodsId
GROUP BY
g.Supplier, g.InitialQuantityToInventory
)
SELECT
Supplier,
SUM(Initial) + SUM(StockChange) AS StockLevel
FROM
Logs
GROUP BY
Supplier
What might be happening is you're getting a row per unique InitialQuantityToInventory, but from what I gather, you want these to be summed, right?
This could probably be optimised further (and probably doesn't need a CTE), but hopefully it at least returns the data you expect.
I don't think you need to GROUP BY InitialQuantityToInventory. Try following query and let me know if this works for what you need.
SELECT
g.PartNum,
g.Supplier,
MAX(g.InitialQuantityToInventory) + SUM(COALESCE(t.AmountInventoryAdjusted + t.AmountReturned,0)) AS StockLevel
FROM
GoodsIn g
LEFT JOIN
Transfers t ON g.GoodsInNumber = t.GoodsInNumber
WHERE
g.PartNum = '123'
GROUP BY
g.PartNum, g.Supplier
Try this, group the Transfers before joining and grouping
SELECT
g.PartNum,
g.Supplier,
SUM(g.InitialQuantityToInventory + COALESCE(t.adjRet, 0))
FROM Goodsin g
LEFT JOIN
(
SELECT GINum, SUM(AmountInventoryAdjusted + AmountReturned) AS adjRet
FROM Transfers
GROUP BY GINum
) T
ON t.GINum = g.GiNum
GROUP BY g.PartNum, g.Supplier

How to combine fields from 2 columns to create a "matrix"?

I have a logging table in my application that only logs changed data, and leaves the other columns NULL. What I'm wanting to do now is create a view that takes 2 of those columns (Type and Status),
and create a resultset that returns the Type and Status on the entry of that log row, assuming that either one or both columns could be null.
For example, with this data:
Type Status AddDt
A 1 7/8/2013
NULL 2 7/7/2013
NULL 3 7/6/2013
NULL NULL 7/5/2013
B NULL 7/4/2013
C NULL 7/3/2013
C 4 7/2/2013
produce the resultset:
Type Status AddDt
A 1 7/8/2013
A 2 7/7/2013
A 3 7/6/2013
A 3 7/5/2013
B 3 7/4/2013
C 3 7/3/2013
C 4 7/2/2013
From there I'm going to figure out the first time in these results the Type and Status meet certain conditions, such as a Type of B and Status 3 (7/4/2013) and ultimately use that date in a calculation, so performance is a huge issue with this.
Here's what I was thinking so far, but it doesn't get me where I need to be:
SELECT
Type.TypeDesc
, Status.StatusDesc
, *
FROM
jw50_Item c
OUTER APPLY (SELECT TOP 10000 * FROM jw50_ItemLog csh WHERE csh.ItemID = c.ItemID AND csh.StatusCode = 'OPN' ORDER BY csh.AddDt DESC) [Status]
OUTER APPLY (SELECT TOP 10000 * FROM jw50_ItemLog cth WHERE cth.ItemID = c.ItemID AND cth.ItemTypeCode IN ('F','FG','NG','PF','SXA','AB') ORDER BY cth.AddDt DESC) Type
WHERE
c.ItemID = #ItemID
So with the help provided below, I was able to get where I needed. Here is my final solution:
SELECT
OrderID
, CustomerNum
, OrderTitle
, ItemTypeDesc
, ItemTypeCode
, StatusCode
, OrdertatusDesc
FROM
jw50_Order c1
OUTER APPLY (SELECT TOP 1 [DateTime] FROM
(SELECT c.ItemTypeCode, c.OrderStatusCode, c.OrderStatusDt as [DateTime] FROM jw50_Order c WHERE c.OrderID = c1.OrderID
UNION
select (select top 1 c2.ItemTypeCode
from jw50_OrderLog c2
where c2.UpdatedDt >= c.UpdatedDt and c2.ItemTypeCode is not null and c2.OrderID = c.OrderID
order by UpdatedDt DESC
) as type,
(select top 1 c2.StatusCode
from jw50_OrderLog c2
where c2.UpdatedDt >= c.UpdatedDt and c2.StatusCode is not null and c2.OrderID = c.OrderID
order by UpdatedDt DESC
) as status,
UpdatedDt as [DateTime]
from jw50_OrderLog c
where c.OrderID = c1.OrderID AND (c.StatusCode IS NOT NULL OR c.ItemTypeCode IS NOT NULL)
) t
WHERE t.ItemTypeCode IN ('F','FG','NG','PF','SXA','AB') AND t.StatusCode IN ('OPEN')
order by [DateTime]) quart
WHERE quart.DateTime <= #FiscalPeriod2 AND c1.StatusCode = 'OPEN'
Order By c1.OrderID
The union is to bring in the current data in addition to the log table data to create the resultset, since the current data maybe what meets the conditions required. Thanks again for the help guys.
Here is an approach that uses correlated subqueries:
select (select top 1 c2.type
from jw50_Item c2
where c2.AddDt >= c.AddDt and c2.type is not null
order by AddDt
) as type,
(select top 1 c2.status
from jw50_Item c2
where c2.AddDt >= c.AddDt and c2.status is not null
order by AddDt
) as status,
(select AddDt
from jw50_Item c
If you have indexes on jw50_item(AddDt, type) and jw50_item(AddDt, status), then the performance should be pretty good.
I suppose you want to "generate a history": for those dates that has some data missing, the next available data should be set.
Something similar should work:
Select i.AddDt, t.Type, s.Status
from Items i
join Items t on (t.addDt =
(select min(t1.addDt)
from Items t1
where t1.addDt >= i.addDt
and t1.Type is not null))
join Items s on (s.addDt =
(select min(s1.addDt)
from Items s1
where s1.addDt >= i.addDt
and s1.status is not null))
Actually I'm joining the base table to 2 secondary tables and the join condition is that we match the smallest row where the respective column in the secondary table is not null (and of course smaller than the current date).
I'm not absolutely sure that it will work, since I don't have an SQL Server in front of me but give it a try :)

SQL query - need to exclude if Requirement NOT met, and exclude if Disqualifier IS met

I have a feeling once i see the solution i'll slap my forehead, but right now I'm not seeing it.
I have a lookup table, say TableB, which looks like this. All fields are INT except the last two which are BOOL.
ID, TableA_ID, Value, Required, Disqualifies
I have a list of TableA_Id values (1, 2, 3 ) etc
For each record in this table, either Required can be true or disqualified can be true - they cant both be true at the same time. They can both be false or null though. There can be duplicate values of TableA_Id but there should never be duplicates of TableA_Id and Value
If required is true for any of those TableA_ID values, and none of those values are in my list, return no records. If none of the values are marked as required (required = 0 or null) then return records UNLESS any of the values are marked as Disqualifies and are in the list, in which case i want to return no records.
So - if a field is required and i dont have it, dont return any records. If a field is marked as disqualified and i have it, don't return any records. Only return a record if either i have a required value or don't have a disqualified value or there are no required values.
I hope I explained myself clearly.
Thanks in advance for pointing me in the right direction.
As an example of what my records might look like:
ID TableA_ID Value Required Disqualifies
-- --------- ----- -------- ------------
1 123 1 True False
2 123 2 True False
3 123 3 False False
4 123 4 False True
5 456 1 False True
6 456 2 False False
Given this set of sample data, if we're working with TableA_Id 123 and my list of values is lets say 1 and 3, i would get data returned because i have a required value and dont have any disqualified values. If my list of values were just 3, i'd get no records since i'm missing of the Required values. If my list of values were 1 and 4, i'd get no records because 4 is marked as disqualified.
Now if we're working with TableA_Id 456, the only list of values that would return any records is 2.
Maybe i should post the whole SQL query - i was trying to keep this short to make it easier for everyone, but it looks like maybe that's not working so well.
Here is the full dynamically generated query. The bit i am working on now is the 2nd line from the bottom. To equate this to my example, t.id would be TableA_ID, Value would be PDT_ID.
SELECT DISTINCT t.ID, t.BriefTitle, stat.Status, lstat.Status AS LocationStatus, st.SType, t.LAgency, l.City, state.StateCode
,( SELECT TOP 1 UserID
FROM TRecruiter
WHERE TrialID = t.ID AND Lead = 1 ), l.ID as LocationID
, l.WebBased
FROM Trial t
INNER JOIN Location l ON t.ID = l.TrialID
FULL JOIN pdt on t.ID = pdt.trialid
FULL JOIN pdm on t.ID = pdm.TrialID
FULL JOIN s on t.ID = s.TrialID
FULL JOIN hy on t.ID = hy.TrialID
FULL JOIN ta on t.ID = ta.TrialID
FULL JOIN stt on t.ID = stt.TrialID
FULL JOIN [Status] stat ON t.StatusID = stat.ID
FULL JOIN st ON t.StudyTypeID = st.ID
FULL JOIN State state ON l.StateID = state.ID
FULL JOIN [Status] lstat ON l.StatusID = lstat.ID
FULL JOIN ts ON t.ID = ts.TrialID
FULL JOIN tpdm ON t.ID = tpdm.TrialID
WHERE ((t.ID IS NOT NULL)
AND (EligibleHealthyVolunteers IS NULL OR EligibleHealthyVolunteers = 1 OR (0 = 0 AND EligibleHealthyVolunteers = 0))
AND (eligiblegenderid is null OR eligiblegenderid = 1 OR eligiblegenderid = 3)
AND ((EligibleMinAge <= 28 AND EligibleMaxAge >= 28) OR (EligibleMinAge <= 28 AND EligibleMaxAge is null) OR (EligibleMinAge IS NULL AND EligibleMaxAge >= 28))
AND (HYID = 6 AND (hy.Disqualify = 0 OR hy.Disqualify IS NULL AND NOT EXISTS (SELECT * FROM hy WHERE t.id = hy.TrialID AND hy.Req =1)) OR HYID = 6 AND hy.req = 1)
AND (PDT_ID IN (1) AND ( pdt.Disqualify = 0 OR pdt.Disqualify IS NULL AND NOT EXISTS (select * from pdt where t.id = pdt.TrialID AND pdt.Req = 1)) OR PDT_ID IN (1) AND (pdt.Req = 1 AND (pdt.Disqualify = 0 or pdt.Disqualify is null )))
) AND ((3959 * acos(cos(radians(34.18)) * cos(radians(l.Latitude)) * cos(radians(l.Longitude) - radians(-118.46)) + sin(radians(34.18)) * sin(radians(l.Latitude)))) <= 300 OR l.Latitude IS NULL) AND t.IsPublished = 1 AND (t.StatusID = 1 OR t.StatusID = 2)
I've changed/shortened some table names just for security/privacy reasons.
Edit:
I think i am close to getting this working, but I'm getting tripped up on the logic again.
I have the following bit of sql:
AND ( exists (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id AND pdT_ID IN (2) ) AND EXISTS (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id ) )
I'm not sure how to structure this. Those two exists statement should make the whole thing true in the following combination:
True & False
True & True
False & False
If it's False & True, then the whole thing is false. In other words if there is a Req =1 AND the PDT_ID that is marked as Req=1 is not in our list (in the example above the list just contains '2') then return false.
EDIT:
I think i finally got it.
AND NOT EXISTS (SELECT * FROM pdt WHERE Disqualify = 1 AND trialid = t.id AND PDT_ID IN (2) )
AND NOT ( NOT exists (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id AND PDT_ID IN (2) ) AND EXISTS (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id ) )
So far this seems to work in testing. Although I'm only working with two values of PDT_ID. If this does resolve my problem, i will come back and give someone the credit for helping me.
SELECT *
FROM TABLEB B
WHERE
(
B.REQUIRED = 1
AND EXISTS
(
SELECT 1
FROM TABLEA A
WHERE A.ID =B.TABLEA_ID
)
)
OR
(
B.REQUIRED != 1
AND B.DISQUALIFIES <> 1
)
OR
(
B.REQUIRED != 1
AND B.DISQUALIFIES = 1
AND EXISTS
(
SELECT 1
FROM TABLEA A
WHERE A.ID =B.TABLEA_ID
)
)
UPDATE - after the EDIT and explanation from OP:
Change the line
FULL JOIN pdt on t.ID = pdt.trialid
To
FULL JOIN (SELECT * FROM pdt BB WHERE
BB.TrialID IN (SELECT AA.ID FROM Trial AA WHERE AA.ID = BB.TrialID) AND
1 > (SELECT COUNT(*) FROM Trial A
LEFT OUTER JOIN pdt B ON B.Req != 1 AND B.Disqualify != 1 AND B.TrialID = A.ID
WHERE B.TrialID IS NULL)) pdt ON t.ID = pdt.TiralID
AND change the line before last from
AND (PDT_ID IN (1) AND ( pdt.Disqualify = 0 OR pdt.Disqualify IS NULL AND NOT EXISTS (select * from pdt where t.id = pdt.TrialID AND pdt.Req = 1)) OR PDT_ID IN (1) AND (pdt.Req = 1 AND (pdt.Disqualify = 0 or pdt.Disqualify is null )))
To
AND PDT_ID IN (1)
(You seem to have found a solution, yet I've decided to share my thoughts about this problem anyway.)
Given you've got a set of TableA IDs, each of which is accompanied by a set of some values, and you want to test the entire row set against this TableB thing using the rules you've set forth, I think the entire checking process might look like this:
Match every pair of TableA.ID and Value against TableB and get aggregate maximums of Required and Disqualifies for every TableA.ID along the way.
Derive a separate list of TableA_ID values with their corresponding maximum values of Required, from TableB. That will be for us to know whether a particular TableA_ID must have a required value at all.
Match the row set obtained at Stage 1 against the derived table (Stage 2) and check the aggregate values:
1) if the actual aggregate Disqualifies for a TableA_ID is 1, discard this TableA_ID set;
2) if a TableA_ID has a match in the Stage 2 derived table and the aggregate maximum of Required that we obtained at Stage 1 doesn't match the maximum Required in the derived table, discard the set as well.
Something tells me that it would be better at this point to move on to some sort of illustration. Here's a sample script, with comments explaining which part of the script implements which part of the description above:
;
WITH
/* this is the row set to be tested and which
is supposed to contain TableA.IDs and Values */
testedRowSet AS (
SELECT
TableA.ID AS TableA_ID,
SomethingElse.TestedValue AS Value,
...
FROM TableA
JOIN SomethingElse ON some_condition
...
),
/* at this point, we are getting the aggregate maximums
of TableB.Required and TableB.Disqualifies for every
TableA_ID in testedRowSet */
aggregated AS (
SELECT
testedRowSet.TableA_ID,
testedRowSet.Value,
...
DoesHaveRequiredValues = MAX(CASE TableB.Required WHEN 1 THEN 1 ELSE 0 END) OVER (PARTITION BY testedRowSet.TableA_ID),
HasDisqualifyingValues = MAX(CASE TableB.Disqualifies WHEN 1 THEN 1 ELSE 0 END) OVER (PARTITION BY testedRowSet.TableA_ID)
FROM testedRowSet
LEFT JOIN TableB ON testedRowSet.TableA_ID = TableB.TableA_ID
AND testedRowSet.Value = TableB.Value
),
/* this row set will let us see whether a particular
TableA_ID must have a required value */
properties AS (
SELECT
TableA_ID,
MustHaveRequiredValues = MAX(CASE Required WHEN 1 THEN 1 ELSE 0 END)
FROM TableB
GROUP BY TableA_ID
),
/* this is where we are actually checking the previously
obtained aggregate values of Required and Disqualifies */
tested AS (
SELECT
aggregated.TableA_ID,
aggregated.Value,
...
FROM aggregated
LEFT JOIN properties ON aggregated.TableA_ID = properties.TableA_ID
WHERE aggregated.HasDisqualifyingValues = 0
AND (properties.TableA_ID IS NULL
OR properties.MustHaveRequiredValues = aggregated.DoesHaveRequiredValues)
)
SELECT * FROM tested

Resources