我需要在我的表中设置一个“放弃”标志,除了每个id的最新结果。我以为我有一个可以在这里工作的查询,但是当我在查询上运行select时,我得到的结果不正确 - 我看到一个案例,它选择了两个特定id的结果。我也使用相同的确切数据获得多个结果。 我在这里做错了什么?
这是我的选择声明:
<asp:DropDownList ID="ddlType" runat="server" DataSourceID="sdsType"
DataValueField="ID" DataTextField="Name" AppendDataBoundItems="true">
<asp:ListItem Value="0" Text="--Please Select--" Selected="True"></asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="rfvType" runat="server" ControlToValidate="ddlType"
InitialValue="0" ErrorMessage="Type required"></asp:RequiredFieldValidator>
<asp:SqlDataSource ID="sdsType" runat="server"
ConnectionString='<%$ ConnectionStrings:TESTConnectionString %>'
SelectCommand="SELECT ID, Name FROM Type"></asp:SqlDataSource>
这是我想要运行的实际查询:
select t.test_row_id, t.test_result_id, t.waived, t.pass, t.comment
from EV.Test_Result
join EV.Test_Result as t on EV.Test_Result.test_row_id = t.test_row_id and EV.Test_Result.start_time < t.start_time and t.device_id = 1219 and t.waived = 0
order by t.test_row_id
答案 0 :(得分:1)
如果我理解正确,你就会遇到问题,因为ON
谓词的基数会返回所有匹配的行。
EV.Test_Result.test_row_id = t.test_row_id
and EV.Test_Result.start_time < t.start_time
此ON
将比较具有相同ID的所有start_time值,并返回结果集的每个组合,其中start_time小于t.start_time。显然,这不是你想要的。
and t.device_id = 1219
and t.waived = 0
这实际上是一个谓词(ON
技术上是一个),但我更喜欢在subquery
/ CTE
中使用它有几个原因:限制行数{ {1}}必须检索并比较。
以下内容可能是您所需要的:
SQL
此查询会在SELECT A.test_row_id
, A.test_result_id
, A.waived
, A.pass
, A.comment
FROM EV.Test_Result A
INNER JOIN (SELECT MAX(start_time) AS start_time
, test_row_id
FROM EV.Test_Result
WHERE device_id = 1219
AND waived = 0
GROUP BY test_row_id
) AS T ON A.test_row_id = T.test_row_id
AND A.start_time < T.start_time
ORDER BY A.test_row_id
谓词中的值之间返回1:M
关系,与您运行的ON
查询不同。
<强>更新强>
由于我怯懦地试图改变M:M
上的查询,我将通过解释基本SO
查询运算符的物理和逻辑顺序来赎回自己:
如您所知,您编写了一个简单的SQL
语句,如下所示:
SELECT
请注意,如果使用聚合函数,则所有其他列必须出现在GROUP BY或其他函数中。
现在,SQL Server要求它们以该顺序编写,尽管它实际上按照以下顺序处理它,值得记忆:
在SELECT - MSDN上找到了更多详细信息,但这就是为什么SELECT <aggregate column>, SUM(<non-aggregate column>) AS Cost
FROM <table_name>
WHERE <column> = 'some_value'
GROUP BY <aggregate column>
HAVING SUM(<non-aggregate column>) > some_value
ORDER BY <column>
运算符中的任何列都必须位于聚合函数组中(SELECT
,{{1} }},SUM
等)...以及为什么我的懒惰代码在您第一次尝试时失败了。 :/
另请注意,MIN
是最后一个(技术上MAX
运算符发生在此之后),没有它,结果不是确定性的,除非ORDER BY
之类的函数强制执行它(认为这发生在TOP
声明。)
希望这有助于解决问题,更好地解决SQL的工作原理。干杯
答案 1 :(得分:0)
您可以按时间戳降序尝试ROW_NUMBER()函数顺序并过滤出具有ROW_NUMBER 1的值;
以下查询应该获取除最新的
之外的每个ID的所有记录我在Oracle下面尝试了一个包含字段的表:id,user_id,record_order和timestamp并且它有效:
select
<table_name_alias>.*
from
(
select
id,
user_id,
row_number() over (partition by id order by record_order desc) as record_number
from
<your_table_name>
) <table_name_alias>
where
record_number <>1;
如果您使用的是Teradata DB,还可以尝试QUALIFY语句。我不确定是否所有数据库都支持此功能。
Select
table_name.*
from table_name
QUALIFY row_number() over (partition by id order by record_order desc) <>1;