使用表联接

时间:2019-11-02 03:32:23

标签: mysql

这是我在这里问的另一个问题的另外一层:Using GROUP BY and ORDER BY in same MySQL query

相同的表结构和问题,除了这次想像过去的选举表现在设置为...

| election_ID | Date       | jurisdiction   | Race          | Seats |
|-------------|------------|----------------|---------------|-------|
| 1           | 2016-11-08 | federal        | president     | 1     |
| 2           | 2016-11-08 | state_district | state senator | 2     |

(最后一条记录的座位设置为2而不是1。)

我想使用席位号来获取每个组的不同记录,这些记录按投票数排序。因此,在这种情况下,请添加以下其他表格...

候选人

| Candidate_ID | FirstName | LastName | MiddleName |
|--------------|-----------|----------|------------|
| 1            | Aladdin   | Arabia   | A.         |
| 2            | Long      | Silver   | John       |
| 3            | Thor      | Odinson  | NULL       |
| 4            | Baba      | Yaga     | NULL       |
| 5            | Robin     | Hood     | Locksley   |
| 6            | Sherlock  | Holmes   | J.         |
| 7            | King      | Kong     | Null       |

过去的竞选人

| ID | PastElection | Candidate | Votes |
|----|--------------|-----------|-------|
| 1  | 1            | 1         | 200   |
| 2  | 1            | 2         | 100   |
| 3  | 1            | 6         | 50    |
| 4  | 2            | 3         | 75    |
| 5  | 2            | 4         | 25    |
| 6  | 2            | 5         | 150   |
| 7  | 2            | 7         | 100   |

我希望获得以下输出:

| election_ID | FirstName | LastName | votes | percent |
|-------------|-----------|----------|-------|---------|
| 1           | Aladdin   | Arabia   | 200   | 0.5714  |
| 2           | Robin     | Hood     | 150   | 0.4286  |
| 2           | King      | Kong     | 100   | 0.2857  |

我尝试设置变量并将其与LIMIT语句一起使用,但变量在限制范围内不起作用。我也尝试过使用ROW_NUMBER()(我没有使用MySQL 8.0,所以这行不通,但我愿意升级,如果愿意的话)或类似的解决方法,例如@row_number:= IF ...,然后根据行号进行过滤,但没有任何效果。

上次尝试查询:

SELECT pe.election_ID as elec,
       pe.Seats as s,
       pecs.row_num,
       c.FirstName,
       c.LastName,
       pecs.max_votes AS votes,
       pecs.max_votes / pecs.total_votes AS percent
FROM past_elections pe
JOIN `past_elections-candidates` pec ON pec.PastElection = pe.election_ID
JOIN (SELECT PastElection, 
             Candidate,
             @row_num := IF(PastElection = @current_election, @current_election + 1, 1) as row_num,
             MAX(Votes) AS max_votes,
             SUM(Votes) AS total_votes,
             @current_election := PastElection
      FROM `past_elections-candidates`
      GROUP BY PastElection) pecs ON pecs.PastElection = pec.PastElection AND pecs.row_num <= pe.Seats
JOIN candidates c ON c.Candidate_ID = pec.Candidate

2 个答案:

答案 0 :(得分:0)

使用MySQL 8而不管;)

使用ROW_NUMBER订购过去的选举:

SELECT *, ROW_NUMBER() OVER(PARTITION BY pastelection ORDER BY votes DESC) as rown 
FROM `past_elections-candidates`

将此作为子查询加入到past_elections中(这只是您在“使用pe.seats来改变每次选举返回的行数”上遇到的麻烦,并且不包含百分比位:

SELECT * 
FROM
  past_elections pe 
  INNER JOIN
  (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY pastelection ORDER BY votes DESC) as rown 
    FROM `past_elections-candidates`
  ) pecr 
  ON pecr.pastelection = pe.electionid AND
     pecr.rown <= pe.seats 

如果您想在升级前在8上进行测试,则db fiddle站点的负载支持v8

ps; y百分比的东西可以与ROW_NUMBER同时完成,例如:

votes/SUM(votes) OVER(PARTITION BY past_election)

例如,选举ID 1的总和为200 + 100 + 50,得出200/350 =〜57%

SELECT *, votes/SUM(votes) OVER(PARTITION BY past_election) as pcnt, ROW_NUMBER() OVER(PARTITION BY pastelection ORDER BY votes DESC) as rown 
FROM `past_elections-candidates`

您需要先进行计算

答案 1 :(得分:0)

我没有列出正确的字段,但这与我今晚可能会得到的距离很近...我已经得到了我需要的行,但是需要加入候选表以使名字出来...

使用Dense_Rank似乎可以解决此问题...

SELECT * FROM (
  SELECT pec.PastElection,
         c.FirstName,
         c.LastName,
         pec.Votes,
         pecs.totalVotes,
         pe.Seats as s,
         DENSE_RANK() OVER(PARTITION BY PastElection ORDER BY Votes DESC) as rank_votes
  FROM `past_elections-candidates` pec
  JOIN (SELECT PastElection,
               Max(Votes) as maxVotes,
               Sum(Votes) as totalVotes
        FROM `past_elections-candidates`
        GROUP BY PastElection) pecs ON pecs.PastElection = pec.PastElection
  JOIN `past_elections` pe ON pec.PastElection = pe.election_ID
  JOIN candidates c ON c.Candidate_ID = pec.Candidate
) t WHERE rank_votes <= s;

这将导致

| PastElection | FirstName | LastName | Votes | totalVotes | s | rank_votes |
|--------------|-----------|----------|-------|------------|---|------------|
| 1            | Aladdin   | Arabia   | 200   | 350        | 1 | 1          |
| 2            | Robin     | Hood     | 150   | 350        | 2 | 1          |
| 2            | King      | Kong     | 100   | 350        | 2 | 2          |

我想在数据中具有rank_votes和s列有点混乱,但是如果得到我需要的结果,这对我来说真的很好。