(SQL)基于多对对从数据库中进行选择

时间:2010-05-07 01:05:48

标签: sql

我遇到的问题是尝试从数据库中选择行,其中该行中的2列与特定数据对对齐。换句话说,从id = 1 AND type = 'news'的数据中选择行。显然,如果它是1个简单对,那将很容易,但问题是我们是根据数百对数据选择行。我觉得好像必须有一些方法来执行此查询而不循环对并单独查询每个。我希望有些SQL堆栈器可以提供指导。

这是一个完整的代码分解:

让我们假设我有以下数据集,其中history_id是主键。 (为了便于阅读,我简化了有关日期的结构。)

table: history
history_id  id  type  user_id  date
1           1   news  1        5/1
2           1   news  1        5/1
3           1   photo 1        5/2
4           3   news  1        5/3
5           4   news  1        5/3
6           1   news  1        5/4
7           2   photo 1        5/4
8           2   photo 1        5/5

如果用户想要根据日期范围从数据库中选择行,我们将获取该数据的子集:

SELECT history_id, id, type, user_id, date
FROM history
WHERE date BETWEEN '5/3' AND '5/5'

返回以下数据集:

history_id  id  type  user_id  date
4           3   news  1        5/3
5           4   news  1        5/3
6           1   news  1        5/4
7           2   photo 1        5/4
8           2   photo 1        5/5

现在,使用该数据子集,我需要确定这些条目中有多少代表数据库中每个类型/ ID配对的第一个条目。换句话说,第4行是数据库中第一个时间id: 3type: news出现了吗?所以我使用with() min()查询。

在实际代码中,两个列表以编程方式从我们先前查询的结果集生成。 (为了便于阅读,我把它拼写出来。)

WITH previous AS (
  SELECT history_id, id, type
  FROM history
  WHERE id IN (1,2,3,4) AND type IN ('news','photo')
) SELECT min(history_id) as history_id, id, type
FROM previous
GROUP BY id, type

返回以下数据集:

history_id  id  type  user_id  date
1           1   news  1        5/1
2           1   news  1        5/1
3           1   photo 1        5/2
4           3   news  1        5/3
5           4   news  1        5/3
6           1   news  1        5/4
7           2   photo 1        5/4
8           2   photo 1        5/5

您会注意到它是整个原始数据集,因为我们在列表中单独匹配id和类型,而不是作为集体对。

我想要的结果就是这个,但我无法弄清楚得到这个结果的SQL:

history_id  id  type  user_id  date
1           1   news  1        5/1
4           3   news  1        5/3
5           4   news  1        5/3
7           2   photo 1        5/4

显然,我可以循环遍历每一对并查询数据库以确定其第一个结果,但这似乎是一个低效的解决方案。我认为这个网站上的一位SQL大师可能会传播一些智慧。

如果我不正确地接近这种情况,整个例程的要点是数据库将所有创建和编辑存储在同一个表中。我需要跟踪每个用户的行为,并确定历史记录表中有多少条目是特定日期范围内的编辑或创建。因此,我根据type:id从日期范围中选择所有user_id对,然后对于每个配对,我确定用户是否负责数据库中出现的第一条记录。如果是第一个,则“创建”否则“编辑”。

3 个答案:

答案 0 :(得分:1)

看不到需要两个查询...... DVK明白了这个想法:

select id, type, MIN(date) as 'min_date'
from history
where date between YOUR_START_DATE and YOUR_END_DATE
group by id, type

答案 1 :(得分:0)

SELECT * 
FROM HISTORY,
    (SELECT    MIN(date) 'min_date', id, type
     FROM      history
     WHERE     id IN (1,2,3,4) AND type IN ('news','photo')
     -- AND DATE BETWEEN xxx and YYY
     GROUP BY  id, type) 'min_dates'
WHERE HISTORY.id     = min_dates.id
 AND  HISTORY.type   = min_dates.type
 AND  HISTORY.date   = min_dates.min_date

这未经过测试,因为我目前没有数据库访问权限,抱歉

答案 2 :(得分:0)

SELECT 
      h1.history_id,
      h1.id,
      h1.type,
      h1.user_id,
      h1.date
   FROM 
      ( select 
              h2.id, 
              MIN( h2.history_id ) minHistory 
           from 
              history h2
           group by
              h2.id ) ByType,
       history h1
   where 
      ByType.MinHistory = h1.History_ID

无论日期如何,这都将查询整个系统。但是,您可以在内部查询“从历史记录h2”中使用您的WHERE条件来限制日期范围或ID类型或类型说明。

由于内部查询将首先完成,并且显然具有较少的记录,因此将用作加入FULL历史表的主要查询。但由于它仅基于单一的历史记录ID记录,因此只有那个关键记录为“第一”才会返回,因为您希望得到它。