T-SQL - 获取已加入条目的计数

时间:2012-09-19 11:45:04

标签: sql sql-server tsql

我想知道如何更好地将以下查询写入Microsoft SQL Server。

我有三个表:surveyssurvey_presetssurvey_scenes。它们包含以下列:

CREATE TABLE [dbo].[surveys](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [caption] [nvarchar](255) NOT NULL,
    [creation_time] [datetime] NOT NULL,
)
CREATE TABLE [dbo].[survey_presets](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [survey_id] [int] NOT NULL,
    [preset_id] [int] NOT NULL,
)
CREATE TABLE [dbo].[survey_scenes](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [survey_id] [int] NOT NULL,
    [scene_id] [int] NOT NULL,
)

survey_presetssurvey_scenes surveys列的survey_id都有外键。

现在我想选择所有调查,每个调查都有相应的预设和场景。这是我想要的“伪查询”:

SELECT
    surveys.*,
    COUNT(survey_presets, where survey_presets.survey_id = surveys.id), 
    COUNT(survey_scenes, where survey_scenes.survey_id = surveys.id)
FROM surveys
ORDER BY suverys.creation_time

我可以对SELECT DISTINCTJOINGROUP BY等进行混乱,但我是T-SQL的新手,我怀疑我的查询在任何意义上都是最优的

2 个答案:

答案 0 :(得分:2)

我会在子查询中进行计数,以避免使用笛卡尔积。由于您在presets中可能会有一些匹配的行,而scenes中的一些行也可能会成倍增加。您可以编写简单的连接查询,并通过计算distinct survey_presets.iddistinct survey_scenes.id来避免乘法。

SELECT
    surveys.*,
    isnull(presets_count, 0) presets_count,
    isnull(scenes_count, 0) scenes_count
FROM surveys
LEFT JOIN 
(
  SELECT survey_id,
         count(*) presets_count
    FROM survey_presets
   GROUP BY survey_id
) presets
  ON surveys.id = presets.survey_id
LEFT JOIN 
(
  SELECT survey_id,
         count(*) scenes_count
    FROM survey_scenes
   GROUP BY survey_id
) scenes
  ON surveys.id = scenes.survey_id
ORDER BY surveys.creation_time

工作原理

您可以向查询的FROM部分引入一种名为derived table的特殊子查询。派生表定义为括在括号中的普通查询,后跟表别名。它不能使用外部查询中的任何列,但可以公开您在ON部分中使用的列,以将派生表连接到查询的主体。

在这种情况下,派生表只计算按id分组的行;联接将计数连接到调查。

答案 1 :(得分:0)

SELECT surveys.ID, surveys.caption, surveys.creation_time,
count(survey_presets.survey_id) as survey_presets,
count(survey_scenes.survey_id)  as survey_scenes
FROM surveys
LEFT OUTER JOIN survey_presets on survey_presets.survey_id = surveys.id 
LEFT OUTER JOIN survey_scenes  on survey_scenes.survey_id  = surveys.id
GROUP BY surveys.ID, surveys.caption, surveys.creation_time
ORDER BY suverys.creation_time