我有一种感觉,一旦我看到解决方案,我会打我的额头,但现在我没有看到它。
我有一个查找表,比如TableB
,看起来像这样。除了最后两个是BOOL之外,所有字段都是INT
。
ID, TableA_ID, Value, Required, Disqualifies
我有一个TableA_Id
值列表(1, 2, 3 )
等
对于此表中的每条记录,要么必须为真,要么取消资格可以为真 - 它们不能同时为真。它们既可以是假的也可以是空的。可能存在TableA_Id
的重复值,但绝不应重复TableA_Id
和Value
如果对于任何这些TableA_ID值都是必需的,并且这些值都不在我的列表中,则不返回任何记录。如果没有任何值被标记为必需(required = 0 or null)
,则返回记录 UNLESS 任何值都被标记为取消资格并且在列表中,在这种情况下我想不返回任何记录。< / p>
所以 - 如果一个字段是必需的,我没有它,不要返回任何记录。如果某个字段被标记为取消资格且我拥有该字段,请不要返回任何记录。如果我有一个必需的值或者没有取消资格或者没有必要的值,则只返回记录。
我希望我能清楚地解释自己。
提前感谢我指出了正确的方向。
作为我的记录可能的样子的一个例子:
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
鉴于这组样本数据,如果我们使用TableA_Id
123并且我的值列表是1和3,我会得到数据,因为我有一个必需的值而且没有任何取消资格值。如果我的值列表只有3,那么我没有记录,因为我缺少必需的值。如果我的值列表是1和4,我将没有记录,因为4被标记为取消资格。
现在,如果我们使用TableA_Id
456,那么唯一可以返回任何记录的值列表是2.
也许我应该发布整个SQL查询 - 我试图保持这个简短,以便让每个人都更容易,但看起来可能不是那么好。
这是完整动态生成的查询。我现在正在处理的是从底部开始的第二行。要将此等同于我的示例,t.id
将为TableA_ID
,Value
将为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)
我出于安全/隐私原因更改/缩短了一些表名。
修改 我认为我已接近完成这项工作,但我再次绊倒了逻辑。
我有以下一点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 ) )
我不确定如何构建它。这两个存在的语句应该在以下组合中使整个事情成为现实: 真实&amp;假 真实&amp;真正 虚假&amp;假
如果它是假的&amp;没错,那么整件事都是假的。换句话说,如果Req = 1并且标记为Req = 1的PDT_ID不在我们的列表中(在上面的示例中,列表只包含'2')则返回false。
修改 我想我终于明白了。
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 ) )
到目前为止,这似乎在测试中起作用。虽然我只使用两个PDT_ID值。如果这确实解决了我的问题,我会回来给别人一个帮助我的功劳。
答案 0 :(得分:0)
更新 - 在编辑和OP解释之后:
更改行
FULL JOIN pdt on t.ID = pdt.trialid
要
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 (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 PDT_ID IN (1)
答案 1 :(得分:0)
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
)
)
答案 2 :(得分:0)
(您似乎找到了解决方案,但我决定分享我对此问题的看法。)
鉴于您有一组TableA
个ID,每个ID都附带一组值,并且您希望使用规则测试针对此TableB
事物的整个行集你提出了,我认为整个检查过程可能如下:
将每对TableA.ID
和Value
与TableB
匹配,并为每Required
获得Disqualifies
和TableA.ID
的汇总最大值一路走来。
从TableA_ID
派生一个单独的Required
值列表及其对应的最大值TableB
。这将是我们知道特定的TableA_ID
是否必须具有所需的值。
将第1阶段获得的行集与派生表(第2阶段)匹配,并检查汇总值:
1)如果Disqualifies
的实际汇总TableA_ID
为1
,则弃置此TableA_ID
集;
2)如果TableA_ID
在第2阶段派生表中匹配,并且我们在第1阶段获得的最大Required
的最大值与最大Required
匹配派生表,也丢弃该集。
有些东西告诉我,在这一点上更好地继续进行某种说明。这是一个示例脚本,其中的注释解释了脚本的哪一部分实现了上述描述的哪一部分:
;
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