【问题标题】:Query count() on multiple columns在多列上查询 count()
【发布时间】:2020-05-17 09:52:06
【问题描述】:

为了练习,我创建了以下数据库。

我希望能够 count() 每个用户在“舞蹈”表中的舞蹈数量。

这是查询

SELECT 
    [user].[id_user], [user].[user_name], 
    COUNT([dance].[dancer_2_id_user]) AS 'number of dances'
FROM 
    [user]
LEFT JOIN 
    [dance] ON [user].[id_user] = [dance].[dancer_2_id_user]
GROUP BY 
    [user].[id_user], [user].[user_name]

返回用户在“dancer_2_id_user”列中计数的次数。

还有这个查询

SELECT 
    [user].[id_user], [user].[user_name], 
    COUNT([dance].[dancer_1_id_user]) AS 'number of dances'
FROM 
    [user]
LEFT JOIN 
    [dance] ON [user].[id_user] = [dance].[dancer_1_id_user]
GROUP BY 
    [user].[id_user], [user].[user_name]

返回用户在“dancer_1_id_user”列中计数的次数。

我想将这两个查询放在一起,因为用户可以出现在“舞蹈”表的任一列中,以便能够计算每个用户的舞蹈总数。

CREATE TABLE [user]
(
    [id_user] INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    [user_name] VARCHAR(45) UNIQUE,
    [User_Sex] CHAR(1),
    [date_of_birth] DATE,
    [account_type] INT,
    [id_address] INT,
);

CREATE TABLE [address]
(
    [id_address] INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    [street] VARCHAR(255),
    [number] INT,
    [locality] VARCHAR(255),
    [city] VARCHAR(255),
    [country_code] CHAR(2)
);

CREATE TABLE [membership]
(
    [account_type] INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    [membership_name] VARCHAR(45),
    [membership_price] DECIMAL(4,2)
);

CREATE TABLE [style]
(
    [style_ref] INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    [style_name] VARCHAR(45)
);

CREATE TABLE [dance]
(
    [id_dance] INT NOT NULL IDENTITY(1,1),
    [dancer_1_id_user] INT,
    [dancer_2_id_user] INT,
    [dance_dtg] DATETIME,
    [style_ref] INT,
    FOREIGN KEY (dancer_1_id_user) REFERENCES [user] (id_user),
    FOREIGN KEY (dancer_2_id_user) REFERENCES [user] (id_user),
    FOREIGN KEY (style_ref) REFERENCES [style] (style_ref)  
);

CREATE TABLE [user_dance_style]
(
    [id_user] INT,
    [style_ref] INT
    FOREIGN KEY (id_user) REFERENCES [user] (id_user),
    FOREIGN KEY (style_ref) REFERENCES [style] (style_ref)
)

ALTER TABLE [user]
   ADD CONSTRAINT fk_user_memebership 
       FOREIGN KEY (account_type) REFERENCES membership (account_type),
       CONSTRAINT fk_user_address 
       FOREIGN KEY (id_address) REFERENCES address (id_address);

-- disable all constraints
EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

INSERT INTO [membership] ([membership_name], [membership_price])
VALUES ('free', '0'), ('regular', '15'), ('premium', '30')

INSERT INTO [style]([style_name])
VALUES ('Salsa'), ('Bachata'), ('Kizomba')
GO

INSERT INTO [user] ([user_name], [User_Sex], [date_of_birth], [account_type], [id_address])
VALUES ('sara', 'f', '1990-04-23', '1', '1'),
       ('elenor', 'f', '1989-02-18', '1', '2'),
       ('eva', 'f', '1987-01-04','1','3'),
       ('mike', 'm', '1985-05-02', '1', '4'),
       ('phil', 'm', '1985-03-01', '1', '5'),
       ('laurent', 'm', '1986-02-14', '2', '6'),
       ('nidia', 'f', '1985-01-16', '2', '7'),
       ('franz', 'm', '1990-03-17', '2', '8'),
       ('stephan', 'm', '1991-05-23', '2', '9'),
       ('sandra', 'f', '1993-03-25', '3', '10'),
       ('virginie', 'f', '1999-05-03', '3', '11'),
       ('claire', 'f', '1992-02-24', '3', '12'),
       ('laurence', 'f', '1991-04-26', '3', '13'),
       ('pierre', 'm', '1987-02-14', '3', '14'),
       ('thierry', 'm', '1989-01-04', '3', '15'),
       ('nancy', 'f', '1950-04-15', '1', '16')
GO

INSERT INTO [address] ([street], [number], [locality], [city], [country_code])
VALUES
('av de l''exposition', '13', 'laeken', 'bruxelles', 'be'),
('rue cans', '2', 'ixelles', 'bruxelles', 'be'),
('rue goffart', '32', 'ixelles', 'bruxelles', 'be'),
('ch de haecht', '17', 'schaerbeek', 'bruxelles', 'be'),
('rue metsys', '108', 'schaerbeek', 'bruxelles', 'be'),
('rue du pré', '223', 'jette', 'bruxelles', 'be'),
('rue sergent sorenser', '65', 'ganshoren', 'bruxelles', 'be'),
('rue d''aumale', '38', 'anderlecht', 'bruxelles', 'be'),
('av de fré', '363', 'uccle', 'bruxelles', 'be'),
('rue de lisbonne', '52', 'saint gilles', 'bruxelles', 'be'),
('av neptune', '24', 'forest', 'bruxelles', 'be'),
('av mozart', '76', 'forest', 'bruxelles', 'be'),
('rue emile delva', '92', 'laeken', 'bruxelles', 'be'),
('av de la chasse', '68', 'etterbeek', 'bruxelles', 'be'),
('rue leopold 1', '42', 'laeken', 'bruxelles', 'be'),
('av charle woeste', '68', 'jette', 'bruxelles', 'be')

GO

INSERT INTO [user_dance_style] ([id_user], [style_ref])
VALUES
(1, 1),(1, 2),(1, 3),(2, 1),(2, 2),(2, 3),(3, 1),(3, 2),(4, 1),(4, 2),
(4, 3),(5, 2),(5, 3),(6, 1),(7, 3),(8, 3),(9, 1),(9, 2),(9, 3),(10, 1),
(10, 2),(10, 3),(11, 3),(12, 2),(13, 2),(14, 1)

GO

INSERT INTO [dance]([dancer_1_id_user], [dancer_2_id_user], [dance_dtg], [style_ref])
VALUES
(1, 2, convert(datetime, '2019-11-24 10:34:09 PM',20), 3),
(4, 2, convert(datetime, '2019-11-24 10:50:00 PM',20), 3),
(3, 5, convert(datetime, '2019-11-24 10:35:00 PM',20), 2),
(6, 1, convert(datetime, '2019-11-24 10:37:00 PM',20), 1),
(7, 2, convert(datetime, '2019-11-24 10:37:00 PM',20), 3),
(8, 1, convert(datetime, '2019-12-03 11:20:03 PM',20), 3),
(9, 3, convert(datetime, '2019-12-23 10:45:00 AM',20), 1),
(10, 12, convert(datetime, '2019-12-26 11:20:00 AM',20), 2),
(11, 4, convert(datetime, '2020-01-02 08:45:00 AM',20), 3),
(12, 5, convert(datetime, '2020-01-02 11:10:04 AM',20), 2),
(13, 12, convert(datetime, '2020-02-04 09:25:00 PM',20), 2),
(14, 10, convert(datetime, '2020-02-25 10:45:00 AM',20), 1),
(2, 14, convert(datetime, '2020-02-25 08:45:00 PM',20), 1),
(5, 10, convert(datetime, '2020-03-01 11:15:06 AM',20), 2)
GO

【问题讨论】:

    标签: sql sql-server join count


    【解决方案1】:

    您可以使用运算符INuserdance 结合起来:

    SELECT u.[id_user], u.[user_name], 
           COUNT(d.id_dance) AS [number of dances]
    FROM [user] u LEFT JOIN [dance] d
    ON u.[id_user] IN (d.[dancer_1_id_user], d.[dancer_2_id_user])
    GROUP BY u.[id_user], u.[user_name]
    

    请参阅demo
    结果:

    > id_user | user_name | number of dances
    > ------: | :-------- | ---------------:
    >       1 | sara      |                3
    >       2 | elenor    |                4
    >       3 | eva       |                2
    >       4 | mike      |                2
    >       5 | phil      |                3
    >       6 | laurent   |                1
    >       7 | nidia     |                1
    >       8 | franz     |                1
    >       9 | stephan   |                1
    >      10 | sandra    |                3
    >      11 | virginie  |                1
    >      12 | claire    |                3
    >      13 | laurence  |                1
    >      14 | pierre    |                2
    >      15 | thierry   |                0
    >      16 | nancy     |                0
    

    【讨论】:

    • 我不知道我们可以做这样的事情COUNT(COALESCE(d.[dancer_1_id_user], d.[dancer_2_id_user]))。很好的解决方案,我今天学到了一些新东西。
    • 我已经编辑过了。您在舞蹈中有一个主键,您可以使用它而不是 coalesce() 更好。
    • @forpas 我不知道加入后IN的用法,我只知道IN和WHERE的用法。我正在寻找有关如何以这种方式使用它的解释,但我找不到其他示例或教程。你能指出我解释的地方吗?
    • 在 ON 子句中使用 IN 并没有什么特别之处。运算符 IN 返回一个布尔值:TRUE 或 FALSE,它可以在布尔值有效的任何地方使用。就像 a.id = b.id 返回 TRUE 或 FALSE 一样。你可以在这里阅读更多:docs.microsoft.com/en-us/sql/t-sql/language-elements/…
    • 谢谢@forpas,实际上,链接中的示例还显示了 IN 与 where 子句的用法,但我想我开始了解如何使用它。我刚刚使用这个魔术重新格式化了我的一个查询。
    【解决方案2】:

    使用union all尝试以下操作

    select
        user_id,
        user_name,
        sum(number_of_dances) as number_of_dances
    from
    (
        SELECT 
            [user].[id_user] as user_id, 
            [user].[user_name] as user_name, 
            count([dance].[dancer_2_id_user]) as number_of_dances
        FROM [user]
        left JOIN [dance]
        ON [user].[id_user] = [dance].[dancer_2_id_user]
        GROUP BY [user].[id_user], [user].[user_name]
    
        union all
    
    
        SELECT 
            [user].[id_user], 
            [user].[user_name], 
            count([dance].[dancer_1_id_user])
        FROM [user]
        left JOIN [dance]
        ON [user].[id_user] = [dance].[dancer_1_id_user]
        GROUP BY [user].[id_user], [user].[user_name]
    
    )val
    group by
        user_id,
        user_name
    

    【讨论】:

    • 谢谢!我实际上只是在我的课程中阅读有关“联合”的章节:) from 语句后面的“val”是什么?
    • @Tanuki 你必须为子查询提供别名,它可以是任何东西,所以我随机选择了val。所以我首先做了两个查询的union all,然后是每个用户的舞蹈总数。
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多