SQL - 识别降低分数的公司

时间:2017-09-29 20:27:18

标签: sql

我正在使用带有companyID,得分和时间戳的表。

运行SELECT会生成一个客户列表及其随时间变化的分数,这里的示例仅限于一个companyID:

https://i.stack.imgur.com/f09aD.png

我想生成一个列表,其中包含得分在最近的两个时间戳上下降了x%的所有companyID,但我对SQL相对较新,并且不确定如何实现这一点。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:0)

SELECT * FROM (
SELECT companyProfileId, engagementScore, row_number() OVER(PARTITION BY companyProfileId ORDER BY createTimeStamp Desc) AS rowNum
FROM _yourTable_) AS foo
WHERE foo.rowNum() <= 2
AND engagementScore * X = y

over Clause mssql希望您使用的是mssql,因为这不适用于其他rdbms&#39;

答案 1 :(得分:0)

这是在MS SQL和MySQL中测试的替代解决方案。我在http://sqlfiddle.com上测试了这个。

这是查询。它可能不是最有效的,但它相当简单。

SELECT
    EN3.companyProfileId
  , EN3.maxCreateTimestamp
  , EN3.secondMaxCreateTimestamp
  , EN4.engagementScore newestEngagementScore
  , EN5.engagementScore secondNewestEngagementScore
  , EN4.engagementScore - EN5.engagementScore AS engagementDifference
  , 100.0 * (EN4.engagementScore - EN5.engagementScore) / EN5.engagementScore percentDifference
FROM
(
    SELECT
        EN1.companyProfileId
      , EN2.maxCreateTimestamp
      , MAX(EN1.createTimestamp) secondMaxCreateTimestamp
    FROM
        engagement EN1
    INNER JOIN
        (
        SELECT
            companyProfileId
          , MAX(createTimestamp) maxCreateTimestamp
        FROM
            engagement
        GROUP BY
            companyProfileId
        ) EN2
    ON
        EN1.companyProfileId = EN2.companyProfileId
    AND EN1.createTimestamp != EN2.maxCreateTimestamp
    GROUP BY
        EN1.companyProfileId
      , EN2.maxCreateTimestamp
) EN3
INNER JOIN
    engagement EN4
ON
    EN3.companyProfileId = EN4.companyProfileId
AND EN3.maxCreateTimestamp = EN4.createTimestamp
INNER JOIN
    engagement EN5
ON
    EN3.companyProfileId = EN5.companyProfileId
AND EN3.secondMaxCreateTimestamp = EN5.createTimestamp
WHERE
    100.0 * (EN4.engagementScore - EN5.engagementScore) / (EN5.engagementScore) < -10.00

这是为MS-SQL设置的测试数据。

CREATE TABLE engagement (
    companyProfileId INT
  , engagementScore INT
  , createTimestamp DATETIME
);
GO

-- Increased 5%, declined 1%, declined 11%; should be returned for 10%.
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1000, 7500 * 1.05 * 0.99 * 0.89, DATEADD(dd, -1, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1000, 7500 * 1.05 * 0.99, DATEADD(dd, -2, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1000, 7500 * 1.05, DATEADD(dd, -3, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1000, 7500, DATEADD(dd, -4, GETDATE())

-- Only has one score; should not be returned.
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1001, 8000, DATEADD(dd, -1, GETDATE())

-- Declined 15%, declined 15%, increased 15%; should not be returned.
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1002, 6000 * 0.85 * 0.85 * 1.15, DATEADD(dd, -1, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1002, 6000 * 0.85 * 0.85, DATEADD(dd, -2, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1002, 6000 * 0.85, DATEADD(dd, -3, GETDATE())

-- Increased 5%, declined 1%, declined 11%; should be returned for 10%.
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1003, 5000 * 1.05 * 0.89, DATEADD(dd, -1, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1003, 5000 * 1.05, DATEADD(dd, -2, GETDATE())

-- Declined 9%, declined 9%; should not be returned for 10%.
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1004, 9250 * 0.91 * 0.91, DATEADD(dd, -1, GETDATE())
INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1004, 9250 * 0.91, DATEADD(dd, -2, GETDATE())
GO

测试数据的MySQL版本非常相似,所以我省略了大部分内容,但它的形式如下:

INSERT INTO engagement(companyProfileId, engagementScore, createTimestamp) 
SELECT 1002, 7500 * 0.85 * 0.85 * 1.15, DATE_ADD(CURDATE(), INTERVAL -1 DAY);

答案 2 :(得分:0)

您可以试试这个,使用窗口功能可以解决您的问题......

select a.name
     , COUNT(case when subject = 'maths' then 1 end) as maths
     , COUNT(case when subject = 'science' then 1 end) as science
from student a
group by a.name