2017-12-04 9 views
0

グループごとに1つの行を返したい場合は、複数の並べ替え列で選択します。重複した質問を避けるために、の土地でここを軽く踏む。グループごとに複数の並べ替えを使用する

SCHEMA:

CREATE TABLE logs (
    id INT NOT NULL, 
    ip_address INT NOT NULL, 
    status INT NOT NULL, 
    PRIMARY KEY id 
); 

DATA:

INSERT INTO logs (id, ip_address, status) 
VALUES ('1', 19216800, 1), 
     ('2', 19216801, 2), 
     ('3', 19216800, 2), 
     ('4', 19216803, 0), 
     ('5', 19216804, 0), 
     ('6', 19216803, 0), 
     ('7', 19216804, 1); 

CURRENT QUERY:

SELECT * 
    FROM logs 
ORDER BY ip_address, status=1 DESC, id DESC 

注:によってソーティングは、事実上状態列をブール値に変換します。 status=1以降のタイブレーカーはidです。このクエリは現在、最初にそれぞれip_addressの正しい行を返し、その後、私はそのために欲しくない他の行を返します。ip_address

CURRENT OUTPUT:

1, 19216800, 1 
2, 19216801, 2 
6, 19216803, 0 
7, 19216804, 1 

今日私の回避策はif ($lastIP == $row['ip_address']) continue;とPHPでフィルタリングすることである:

1, 19216800, 1 
3, 19216800, 2 
2, 19216801, 2 
6, 19216803, 0 
4, 19216803, 0 
7, 19216804, 1 
5, 19216804, 0 

はOUTPUT WANTED。しかし、私はこのロジックをMySQLに移行したいと考えています。

+0

@Strawberry良いコールを、感謝を。私はクエリの現在の出力を追加し、出力を求めました。 –

答えて

1

これを試してみてください -

SELECT MIN(id), ip_address, status 
FROM logs 
GROUP BY ip_address, status 
+0

したがって、基本的に 'status = 'completed''の真偽値に対して各ip_addressに対して正しい' id'を取得します。ありがとう、これは非常に近いので、私は 'ip_address'ごとに一つの行にしたいと思っています。 –

0

ソリューションの何百ものMySQLで最大-N-グループごとの問題のために既に存在しているので、私は以来、窓関数でCTE構文でこれらの質問に答える開始するつもりですこれはMySQL 8.0.3で利用可能になりました。

WITH sorted AS (
    SELECT id, ip_address, status, 
     ROW_NUMBER() OVER (PARTITION BY ip_address ORDER BY status) AS rn 
    FROM logs 
) 
SELECT * FROM sorted WHERE rn = 1; 
+0

ありがとう、これは非常に素晴らしい長期的な解決策です。私はいつかこれをすぐに使うことができますように! –

+0

8.0がGAからリリースされたら、CTEソリューションを追加するために、最も人気のあるグループごとの最高の回答を編集します。 –

-2

これを試してみてください:

SELECT 
l.`ip_address` , l.`status` 
FROM 
    `logs` l 
GROUP BY l.`ip_address` 
ORDER BY l.`status` = 1 DESC 
+1

_never_結果をグループ化する場合は 'SELECT *'。 https://stackoverflow.com/questions/31697469/mysql-what-happens-to-non-aggregated-fields-upon-a-group-by/31697752#31697752 –

+0

ありがとうございました...編集されました –

関連する問題