An example of my database table

film id | scene id | value id
-----------------------------
   0    |     0    |     7
   0    |     1    |     1
   0    |     1    |     0
   1    |     2    |     8
   1    |     2    |     3
   1    |     3    |     1
   2    |     4    |     3
   2    |     4    |     7
   2    |     5    |     2

I want to select rows where the value id is equal to 8 or 3 only if they are both in a row with the same scene id.

My desired result would be:

film id | scene id | value id
-----------------------------
   1    |     2    |     8
   1    |     2    |     3

I tried grouping by count of scene id but it would output this:

film id | scene id | value id
-----------------------------
   1    |     2    |     8
   1    |     2    |     3
   2    |     4    |     3

where the last row was included because there were multiple values of scene id.

有帮助吗?

解决方案

for selecting values based on a specific column being the same you could have a look at NTILE

Distributes the rows in an ordered partition into a specified number of groups. The groups are numbered, starting at one. For each row, NTILE returns the number of the group to which the row belongs.

there are actually many options, including common_table_expression

on your example:

--==================================================================================
use tempdb
if object_id('tempdb..radhe','U') is not null
   drop table radhe

create table  radhe(
 [Film Id] int not null
,[Scene Id] int not null
,[Value Id]int not null
)


insert into radhe ([Film Id],[Scene Id],[Value Id])
select 
   0    ,     0    ,     7
union all select 
   0    ,     1    ,     1
union all select 
   0    ,     1    ,     0
union all select 
   1    ,     2    ,     8
union all select 
   1    ,     2    ,     3
union all select 
   1    ,     3    ,     1
union all select 
   2    ,     4    ,     3
union all select 
   2    ,     4    ,     7
union all select 
   2    ,     5    ,     2



--I want to select rows 
--where the value id is equal to 8 or 3 
--only if they are both in a row with the same scene id.


--using a cte
;with t8 as (

        SELECT r.[Film Id], r.[Scene Id], r.[Value Id]
        FROM radhe r
        WHERE r.[Value Id]IN (8) 
) ,
t3 as (


        SELECT r.[Film Id], r.[Scene Id], r.[Value Id]
        FROM radhe r
        WHERE r.[Value Id]IN (3) 
)

select t8.* 
from t8
inner join t3
        on t8.[Scene Id] = t3.[Scene Id]
union all
select t3.* 
from t8
inner join t3
        on t8.[Scene Id] = t3.[Scene Id]

--====================================================================

--using NTILE
select r.[Film Id], r.[Scene Id], r.[Value Id]
from
(
SELECT 
    NTILE(2) OVER (ORDER BY [Scene Id]) [NTILE],
    *
FROM Radhe
WHERE [Value Id]IN (3,8) 
) r
where r.NTILE = 1

enter image description here

the results are the same but what about the performance?

enter image description here

check this and this out.

其他提示

Your requirement is clear for current sample data. But there can be so many scenario.

Another approach, same sample data

use tempdb
if object_id('tempdb..radhe','U') is not null
   drop table radhe

create table  radhe(
 [Film Id] int not null
,[Scene Id] int not null
,[Value Id]int not null
)


insert into radhe ([Film Id],[Scene Id],[Value Id])
select 
   0    ,     0    ,     7
union all select 
   0    ,     1    ,     1
union all select 
   0    ,     1    ,     0
union all select 
   1    ,     2    ,     8
union all select 
   1    ,     2    ,     3
union all select 
   1    ,     3    ,     1
union all select 
   2    ,     4    ,     3
union all select 
   2    ,     4    ,     7
union all select 
   2    ,     5    ,     2

Create another temp table or table variable.In this table pre insert the desire condition.

declare @t table([Scene Id] int not null,[Value Id]int not null)
insert into @t values(2,8),(2,3)

Final query

select r.*
   from radhe r inner join @t t on 
    r.[Scene Id] = t.[Scene Id] and r.[Value Id] = t.[Value Id]

So like I told you, if I know the exact requirement and diffrent scenario.Then I will pre populate my table accordingly.

Depending upon exact requirement,it has its limitation.

What about this solution?

create table FILM
(
  film_id  NUMBER,
  scene_id NUMBER,
  value_id NUMBER
)

insert into FILM ([film_id],[scene_id],[value_id])
select 
   0    ,     0    ,     7
union all select 
   0    ,     1    ,     1
union all select 
   0    ,     1    ,     0
union all select 
   1    ,     2    ,     8
union all select 
   1    ,     2    ,     3
union all select 
   1    ,     3    ,     1
union all select 
   2    ,     4    ,     3
union all select 
   2    ,     4    ,     7
union all select 
   2    ,     5    ,     2
union all select
   3    ,     2    ,     3
union all select
   3    ,     2    ,     8
union all select
   3    ,     5    ,     9

Final Query:

select t.*
  from FILM t
 where t.value_id in (8, 3)
   and exists (select t2.film_id, t2.scene_id, t2.value_id
          from film t2
         where t.scene_id = t2.scene_id
           and t2.value_id = 8)

Output :

film id | scene id | value id
-----------------------------
   1    |     2    |     3
   1    |     2    |     8
   3    |     2    |     8   
   3    |     2    |     3
许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top