web-dev-qa-db-ja.com

レコード数と最小/最大値を取得するMySQLクエリで値をGROUP_CONCAT DISTINCTする方法は?

MySQLを実行しています5.0.88 (Coldfusion8)

製品テーブル全体で_number-of-results_および_min/max prices/rebates_をクエリしている製品検索があります。また、_distinct sizes/colors_の文字列を含めたいので、結果を表示しながら検索条件を更新できます。

ただし、私のGROUP_CONCATはすべての期待値を返しません。何が欠けているのかわかりませんが、レコードセット全体でall異なるサイズ/色を返すのではなく、異なる_min/max_サイズ/色を返すだけのようです。

私の製品表:

_ CREATE TABLE dummy (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`iln` VARCHAR(13) NULL DEFAULT NULL,
`ean` VARCHAR(35) NULL DEFAULT NULL,
`artikelnummer` VARCHAR(35) NULL DEFAULT NULL,
`groesse` VARCHAR(10) NULL DEFAULT NULL,
`farbe` VARCHAR(35) NULL DEFAULT NULL,
`farbnummer` VARCHAR(10) NULL DEFAULT NULL,
`preis_ek` DECIMAL(12,2) NULL DEFAULT NULL,
`preis_vk` DECIMAL(12,2) NULL DEFAULT NULL,
`preis_aktuell` DECIMAL(12,2) NULL DEFAULT NULL,
`firma` VARCHAR(35) NULL DEFAULT NULL,
`marke` VARCHAR(35) NULL DEFAULT NULL,
`nos` VARCHAR(4) NULL DEFAULT NULL,
`nos_anzeige` VARCHAR(4) NULL DEFAULT NULL,
`aktiv` VARCHAR(4) NULL DEFAULT NULL,
`modus` VARCHAR(4) NULL DEFAULT NULL,
`bestand` DECIMAL(10,0) NULL DEFAULT '0'
    )
_

製品はEANでリストされているため、たとえば、サイズS、M、L、XLのシャツには、次のような4つのエントリがあります。

_  style      ean           size       price      qty
  123      111111111111    S          9.99       12
  123      111111111112    M          9.99        1
  123      111111111113    L          9.99       23
  123      111111111114    XL         9.99        0
_

これが私のクエリです:

_ SELECT   COUNT(recordcount) AS total_records
        , MIN(min_price_ek) AS ek_min
        , MAX(max_price_ek) AS ek_max
        , MIN(min_price_vk) AS vk_min
        , MAX(max_price_vk) AS vk_max
        , MAX(max_reb) AS rb_max
        , SUBSTRING_INDEX( GROUP_CONCAT( DISTINCT sizeRange ), ',', 10  ) AS sz_rng
        , SUBSTRING_INDEX( GROUP_CONCAT( DISTINCT colorRange ), ',', 16  ) AS cl_rng 

    FROM (SELECT  a.id AS recordcount
                , a.nos
                , a.nos_anzeige
                , MAX(IFNULL(p.ek, a.preis_ek)) AS max_price_ek
                , MIN(IFNULL(p.ek, a.preis_ek)) AS min_price_ek
                , MAX(IFNULL(p.vk, a.preis_vk)) AS max_price_vk
                , MIN(IFNULL(p.vk, a.preis_vk)) AS min_price_vk
                , ROUND( MAX(  ( IFNULL(p.ek, a.preis_ek) - IFNULL(p.vk ,a.preis_aktuell) ) /  IFNULL(p.ek, a.preis_ek)  ),2) AS max_reb
                , a.groesse AS sizeRange
                , zu.systemfarbe AS colorRange 

                FROM artikelstammdaten a

                # currency join
                LEFT JOIN preislisten p ON 
                    p.iln = a.iln 
                AND p.ean = a.ean 
                AND ( (  p.preisliste = "Test" AND p.iln = "2222222222222" ) OR (1=0) )

                # base color join
                LEFT JOIN farbenzuordnung zu ON 
                    a.farbe = zu.farbe 

                WHERE a.aktiv = "ja"
                # include currency if applicable
                AND ( IF( a.iln IN ( 2222222222222), p.onlinepreis IS NOT NULL,1 ) )

                AND a.artikelnummer LIKE "%style_number%"


            GROUP BY a.iln, a.artikelnummer
            HAVING (( sum(a.bestand) != 0 ) OR (a.nos = "ja" AND a.nos_anzeige = "ja" ))
            ) AS temp 
_

販売者(_a.iln_)とスタイル(_a.artikelnummer_)でグループ化する必要があります。 having句は、在庫がある製品(sum(a.bestand) != 0)のみを選択するか、在庫切れにならない(_a.nos_製品に設定され、_a.nos_anzeige_機能がアクティブな)製品のみを選択します)。

私の問題は、これらの行で行われる異なるサイズ/色を選択することです:

_  , SUBSTRING_INDEX( GROUP_CONCAT( DISTINCT sizeRange ), ',', 10  ) AS sz_rng
  , SUBSTRING_INDEX( GROUP_CONCAT( DISTINCT colorRange ), ',', 10  ) AS cl_rng
   ....
  , a.groesse AS sizeRange
  , zu.systemfarbe AS colorRange  
_

これは正しく機能しません。上記の記事は_s,xl_と_s,m,l,xl_のみを返しますが、その理由はよくわかりません。 _SUBSTRING_INDEX_を使用して、最初の10のサイズ/色のみを選択しています(TOP 10の方が良いでしょう)が、これが問題であるかどうかはわかりません。

質問:
構文に問題があり、すべての異なるサイズ/色が返されるわけではありませんか? returだけする方法はありますか

6
frequent

OK。これをしばらく試し、@ Shlomi Noachのコメントを念頭に置いて、次のことを思いつきました。

  • _a.groesse_および_zu.systemfarbe_でグループ化する
  • これはrecordcountをスローします(スタイル番号(_a.artikelnummer_)でグループ化されなくなったようです)
  • COUNT(recordcount) AS total_recordsを削除し、代わりに_a.artikelnummer AS styles_をサブクエリで使用してCOUNT(DISTINCT styles) AS total_recordsを使用します。

したがって、私のクエリは次のようになります。

_ SELECT 
        COUNT(DISTINCT styles) AS total_records
      , MIN(min_price_ek) AS ek_min
      , MAX(max_price_ek) AS ek_max
      , MIN(min_price_vk) AS vk_min
      , MAX(max_price_vk) AS vk_max
      , MAX(max_reb) AS rb_max
      , SUBSTRING_INDEX( GROUP_CONCAT( DISTINCT sizeRange ), ',', 10  ) AS sz_rng
      , SUBSTRING_INDEX( GROUP_CONCAT( DISTINCT colorRange ), ',', 16  ) AS cl_rng

      FROM (SELECT  
             a.artikelnummer AS styles
           , a.nos
           , a.nos_anzeige
           , MAX(IFNULL(p.ek, a.preis_ek)) AS max_price_ek
           , MIN(IFNULL(p.ek, a.preis_ek)) AS min_price_ek
           , MAX(IFNULL(p.vk, a.preis_vk)) AS max_price_vk
           , MIN(IFNULL(p.vk, a.preis_vk)) AS min_price_vk
           , ROUND( MAX(  ( IFNULL(p.ek, a.preis_ek) - IFNULL(p.vk ,a.preis_aktuell) ) /  IFNULL(p.ek, a.preis_ek)  ),2) AS max_reb
           , a.groesse AS sizeRange
           , zu.systemfarbe AS colorRange

           ...
            GROUP BY  a.iln, a.artikelnummera.groesse, zu.systemfarbe
            HAVING (( sum(a.bestand) != 0 ) OR (a.nos = "ja" AND a.nos_anzeige = "ja" ))
            ) AS temp
_

動作しているようで、クエリの処理時間もほぼ同じです。これが他の/より簡単な方法でできるなら、私は厳しい改善提案を受け入れるつもりです。

ありがとう!

1
frequent

[〜#〜] update [〜#〜]これでエラーが表示されます。内部クエリは集計を使用し、集計する列ではないsizeRangeを取り出します。したがって、その列の「サンプル」のみを取得します。厳密に言うと、クエリは有効なSQLではありませんが、MySQLでは緩和されたsql_modeが指定されているため許可されます。

したがって、クエリは本質的に誤りです。修正できるかどうか確認します。

元の回答

group_concat_max_lenの値を確認すると思います。

デフォルトでは単に1024ですが、通常は制限を設けたくありません。

問題は、部分的な結果しか得られていない可能性があります。偶然に、または評価の順序で、「S」と「XL」が最初の1024文字以上を占める場合があります。 「M」または「L」が存在しない理由はわかりません-GROUP_CONCATはそのような区別をしません。

だから、試してみてください:

SET group_concat_max_len := 1000000;

そして、もう一度クエリを実行します。これが機能する場合は、MySQL構成ファイルで上記のパラメーターを設定してください。

私の 関連記事 が役に立つかもしれません。

2
Shlomi Noach