【问题标题】:How do I filter out data that has duplicate values under a specific column?如何过滤掉特定列下具有重复值的数据?
【发布时间】:2015-05-19 14:53:12
【问题描述】:

我有一个包含调查结果的表格:

submitter   issue       q1  q2  q3  q4  q5

mike         11557      4   3   4   5   1
mark         13554      5   5   5   5   5
luke         15110      1   1   1   1   1
luke         15110      1   1   1   1   1
donald       16900      4   2   2   4   5
joe          11562      5   5   5   5   5
joe          11562      5   5   5   5   5
sam          12485      2   3   4   3   4
sam          12485      2   3   4   3   4
sam          12485      2   3   4   3   4

我希望能够过滤掉多个提交并仅计算其中的 1 个。 有些人提交了 3 或 4 次。

我知道如何知道调查提交了多少次以及由谁提交:​​

SELECT
    submitter
    ,issue
    ,COUNT(*) as '# of times Survey submitted'

FROM
    Survey

GROUP BY
    submitter, issue

HAVING
    COUNT(*) > 1

但是,我不确定如何使用此查询来过滤掉多个提交。

我正在处理的当前查询是:

SELECT 'Question #1' as 'Survey Question'
,CAST(CAST(SUM(q1) AS float)/COUNT(q1) AS decimal (4,2)) as 'Average Score'

FROM Survey
WHERE COALESCE(q1,q2,q3,q4,q5) IS NOT NULL

UNION ALL

SELECT 'Question #2' as 'Survey Question'
,CAST(CAST(SUM(q2) AS float)/COUNT(q2) AS decimal (4,2)) as 'Average Score'
FROM Survey
WHERE COALESCE(q1,q2,q3,q4,q5) IS NOT NULL

UNION ALL

etc...

期望的结果是:(注意:这个结果集不准确。只是我想要的格式。)

Survey Question Average Score
Question #1      4.58
Question #2      4.80
Question #3      4.60
Question #4      4.59
Question #5      4.64

谁能提供线索?

非常感谢!

【问题讨论】:

  • 你用的是什么关系型数据库?
  • 您如何决定您将计算多份提交中的哪一项?请同时显示您的预期结果
  • 提交的内容都是一样的(来自任何特定用户),所以没关系。

标签: sql sql-server-2012 survey


【解决方案1】:

我认为我的数学计算是正确的,但我的结果与您的结果不完全相符。你确定你想要的结果是正确的吗?

DECLARE @yourTable TABLE (submitter VARCHAR(10), Issue INT, q1 TINYINT, q2 TINYINT,q3 TINYINT, q4 TINYINT,q5 TINYINT);
INSERT INTO @yourTable
VALUES  ('mike',11557,4,3,4,5,1),
        ('mark',13554,5,5,5,5,5),
        ('luke',15110,1,1,1,1,1),
        ('luke',15110,1,1,1,1,1),
        ('donald',16900,4,2,2,4,5),
        ('joe',11562,5,5,5,5,5),
        ('joe',11562,5,5,5,5,5),
        ('sam',12485,2,3,4,3,4),
        ('sam',12485,2,3,4,3,4),
        ('sam',12485,2,3,4,3,4);

WITH CTE_Distinct
AS
(
    SELECT DISTINCT *
    FROM @yourTable  --just change this to your actual table name.
)

SELECT  REPLACE(question,'q','Question #')   AS [Survey Question],
        CAST(AVG(val * 1.0) AS DECIMAL(4,2)) AS [Average Score]
FROM CTE_Distinct
UNPIVOT
(
    val FOR question IN (q1,q2,q3,q4,q5)
) unpvt
GROUP BY question

结果:

Survey Question     Average Score
-------------------- ---------------------------------------
Question #1          3.50
Question #2          3.17
Question #3          3.50
Question #4          3.83
Question #5          3.50

【讨论】:

  • 感谢您输入斯蒂芬。我将如何查询数据库以获取调查的值,而不是像您那样输入它们?
  • 只需将@yourTable 更改为您的实际表名。显然,您不必声明它或插入值,因此您可以删除这些部分。
  • 太好了,非常感谢斯蒂芬。非常感谢您的帮助。
【解决方案2】:
WITH TestData AS (
    SELECT *
    FROM (VALUES
        ('Mike', 11557, 4, 3, 4, 5, 1)
      , ('Mark', 13554, 5, 3, 5, 5, 5)
      , ('Luke', 15110, 1, 1, 1, 1, 1)
      , ('Luke', 15110, 1, 1, 1, 1, 1)
      , ('Donald', 16900, 4, 2, 2, 4, 5)
      , ('Joe', 11562, 5, 5, 5, 5, 5)
      , ('Joe', 11562, 5, 5, 5, 5, 5)
      , ('Sam', 12485, 2, 3, 4, 3, 4)    
      , ('Sam', 12485, 2, 3, 4, 3, 4)    
      , ('Sam', 12485, 2, 3, 4, 3, 4)    
    ) A (Submitter, Issue, Q1, Q2, Q3, Q4, Q5)
)
SELECT SurveyQuestion
     , AverageScore = AVG(QuestionAnswer * 1.) -- Change the math here if this isn't what you want 
FROM (    
    SELECT A.Submitter
         , A.Issue
         , B.SurveyQuestion
         , B.QuestionAnswer
         , RowNum = ROW_NUMBER() OVER(PARTITION BY A.Submitter, A.Issue, B.SurveyQuestion ORDER BY (SELECT NULL)) -- Replace ORDER BY (SELECT NULL) with something more meaningful if you can
    FROM TestData A
    CROSS APPLY(VALUES -- Unpivot
        ('Question #1', A.Q1)
      , ('Question #2', A.Q2)
      , ('Question #3', A.Q3)
      , ('Question #4', A.Q4)
      , ('Question #5', A.Q5)
    ) B (SurveyQuestion, QuestionAnswer)
    WHERE B.SurveyQuestion IS NOT NULL
) A
WHERE RowNum = 1
GROUP BY SurveyQuestion;

【讨论】:

  • 非常感谢您对 Kittoes 的询问。你知道我如何能够查询数据(值)而不是输入它们吗?
  • 我不确定你的意思。我假设您指的是问题 1-5 被硬编码到 CROSS APPLY 中的事实。使这部分更加动态的唯一方法是编写一些动态 SQL。如果您指的是测试数据,那么只需将其放入表中并将FROM TestData 替换为FROM <your table name>。
  • 是的,我指的是测试数据。再次感谢您的帮助,Kittoes。
【解决方案3】:

我认为您可以应用的第一个解决方案是:选择提交者和问题以及每个提交者给出的每个答案的最大值:

    select submitter, issue, 
       (select max(q1) 
           from survey 
          where submitter = parent.submitter 
            and issue = parent.issue) as q1,
       (select max(q2) 
           from survey 
          where submitter = parent.submitter 
            and issue = parent.issue) as q2,
       (select max(q3) 
           from survey 
          where submitter = parent.submitter 
            and issue = parent.issue) as q3,
       (select max(q4) 
           from survey 
          where submitter = parent.submitter 
            and issue = parent.issue) as q4,
       (select max(q5) 
           from survey 
          where submitter = parent.submitter 
            and issue = parent.issue) as q5
from survery as parent
group by submitter, issue; 

但是这个解决方案的问题是它给出了例如每个问题的最佳答案,这可能不是所需的输出。

另一种方法是为每个寄存器添加一个 id:

alter table survery add id bigint auto_increment;

使用将每一行标记为不同的 id,这是另一条 keetle 的鱼。选择要简单得多:

    select *
      from survey
      where (submitter, issue, id ) in 
      (
    select submitter, issue, max(id)
      from survey 
     group by submitter, issue);

内部选择(具有分组依据的选择)标识您想要获取的 id,第二个选择检索所有信息:提交者、id 和答案。您可以将它与 max() 一起使用来检索最后一个答案作为 good 答案,或者您可以将它与 min() 一起使用来检索第一个答案。

更新

抱歉,我没有看到您提出的“平均”要求。如果您想要一个平均值而不是答案,我谦虚地推荐第二种方法。选择将是:

    select avg(q1) as avg_q1, 
           avg(q2) as avg_q2, 
           ....
      from survey
      where (submitter, issue, id ) in 
      (
    select submitter, issue, max(id)
      from survey 
     group by submitter, issue);

【讨论】:

  • 感谢您的意见,劳尔。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-08
  • 1970-01-01
  • 2019-01-23
  • 2020-05-31
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
相关资源
最近更新 更多