Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
棘手的SQL问题_Sql_Exists - Fatal编程技术网

棘手的SQL问题

棘手的SQL问题,sql,exists,Sql,Exists,我有一张这样的桌子 Key Seq Val A 1 123 A 4 129 A 9 123 A 10 105 B 3 100 B 6 101 B 12 102 我想找到像A,4这样的情况,其中123的值在A,1之前和A,9之后是相同的。 seq严格增加,但可能存在缺口。 有什么建议吗?我没想到这会在数千行中引起轰动: SELECT * /* TODO

我有一张这样的桌子

Key  Seq     Val 
A     1      123
A     4      129 
A     9      123
A     10     105 
B     3      100
B     6      101
B     12     102
我想找到像A,4这样的情况,其中123的值在A,1之前和A,9之后是相同的。 seq严格增加,但可能存在缺口。
有什么建议吗?

我没想到这会在数千行中引起轰动:

SELECT
    * /* TODO - pick columns */
FROM
    Table t1
        inner join
    Table t2
        on
            t1.Key = t2.Key and
            t1.Seq < t2.Seq
        inner join
    Table t3
        on
            t1.Key = t3.Key and
            t1.Seq > t3.Seq and
            t2.Val = t3.Val
        left join
    Table t4
        on
            t1.Key = t4.Key and
            t1.Seq < t4.Seq and
            t4.Seq < t2.Seq
        left join
    Table t5
        on
            t1.Key = t5.Key and
            t1.Seq > t5.Seq and
            t5.Seq > t3.Seq
WHERE
     t4.Key is null and t5.Key is null

基本上,根据您的定义,表的前3个实例连接表本身以查找围绕一个有趣行的两行。后续的连接t4和t5确保t2和t3搜索找到的行与t1行最接近。

编辑:在您提到SQL Server 2000之前,我写了这个。这在SQL Server 2005或更高版本中有效,因此对您没有帮助,但我将把它留给后代:

我使用a向表中添加连续的不间断顺序,然后连接两次以获得上一行和下一行

declare @t table (k char(1), seq int, val int)

insert into @t values ('A', 1, 100)
insert into @t values ('A', 4, 101)
insert into @t values ('A', 9, 100)
insert into @t values ('A', 10, 105)
insert into @t values ('B', 3, 100)
insert into @t values ('B', 6, 101)
insert into @t values ('B', 12, 102)

; with q as (
    select *, row_number() over (partition by k order by seq) [rownum] from @t
)     
select * 
from q
join q q1 on q1.rownum=q.rownum-1 and q.k=q1.k
join q q2 on q2.rownum=q.rownum+1 and q.k=q2.k
where q1.val=q2.val

如果您不需要seq字段,则此选项有效:

;with cte as
(
select COUNT( 1 ) as cnt, val, [key] from tbl 
group by val, [key]
)
select * from cte where cnt > 1
如果您:

;with cte as
(
select COUNT( 1 ) as cnt, val, [key] from tbl 
group by val, [key]
)
select tbl.* from tbl inner join cte on cte.cnt > 1 and cte.[Key] = tbl.[Key] and cte.Val = tbl.Val
编辑:一种tmptbl方法,不提供以下信息:

CREATE TABLE #tmptbl (
    cnt int,
    [key] nchar(10),
    Val nchar(10)
 )

insert into #tmptbl
select COUNT( 1 ) as cnt, [key], Val from tbl 
group by tbl.Val, tbl.[key]
select * from #tmptbl where cnt > 1

drop table #tmptbl

根据您字段的类型,这可能很容易更改,以便为您提供seq。

尽管我只是在sql server 2005中测试了这一点,因为我周围没有2000个实例,但在用实际表替换@t之后,这应该仍然适用于该平台

select k, seq, val
from (
    select k, seq, val,
          (select top 1 val from @t aux where aux.k = main.k and aux.seq < main.seq order by seq desc) as prev_val,
          (select top 1 val from @t aux where aux.k = main.k and aux.seq > main.seq order by seq asc) as next_val
    from @t main
) x
where prev_val = next_val

如果你想查看前两个或更多的值,这肯定会有它自己的作用,因为你可以写lagval,2来向后看2行等等。查找前一个或下一个值是一个简单的情况,选择前1。。。处理得很好。]

假设表名为table,这里是普通的sql

SELECT 
Key, 
Seq 
from Table A
WHERE EXISTS
 (SELECT 1 FROM Table B, Table C 
   WHERE B.Key = A.Key
     AND C.Key = A.Key
     AND B.Seq = (SELECT MAX(Seq) FROM Table D WHERE D.Key = A.Key AND D.Seq < A.Seq) --This ensures that B retrieves previous row
     AND C.Seq = (SELECT MIN(Seq) FROM Table E WHERE E.Key = A.Key AND E.Seq > A.Seq) --This ensures that C retrieves next row
     AND B.Val = C.Val
 )

如果两边的值相同,您能重新表述一下吗?我不明白你想做什么val是一个回文数字,或者只是第一个和最后一个数字相同?SQL的味道是什么?值必须是哪一边的?好的,我把问题改写得更清楚一点你使用的是哪种数据库产品?按k顺序按seq分区不是更好/更清晰,因为每个k值都是分开的吗?是的,这更符合逻辑。已编辑。不幸的是,SQL Server 2000中没有CTE和ROW_编号:-@marc wow,我知道CTE是新的,但我没有意识到ROW_编号不在2000年..所有这些排名函数ROW_编号、排名、密集排名等都是SQL Server 2005的新功能。。。此外:SQLServer2000已经很老了——这个星球上的任何人都不应该再被迫使用它了。。。我也是我自己——不幸的是!不幸的是,OP要求使用SQL Server 2000-目前还没有任何CTE:-啊,我开始时没有指定。尽管如此,对于其他有同样问题的人来说可能还是有用的,但是对于现代数据库来说。OP可以用tmp表做类似的事情吗?很好的解决方案。我只是稍微喜欢阿拉克尼德的简单回答。
SELECT 
Key, 
Seq 
from Table A
WHERE EXISTS
 (SELECT 1 FROM Table B, Table C 
   WHERE B.Key = A.Key
     AND C.Key = A.Key
     AND B.Seq = (SELECT MAX(Seq) FROM Table D WHERE D.Key = A.Key AND D.Seq < A.Seq) --This ensures that B retrieves previous row
     AND C.Seq = (SELECT MIN(Seq) FROM Table E WHERE E.Key = A.Key AND E.Seq > A.Seq) --This ensures that C retrieves next row
     AND B.Val = C.Val
 )