0

名前に英字と数字の両方が含まれている製品名のクエリの出力を並べ替える必要があります。

変数を数値(+0など)に変換するさまざまなソリューションをすでに見つけており、製品名の数値部分をソートしています。ただし、製品名の文字列の前の部分はさまざまな長さであるため、名前はアルファベット順に並べ替えられていません。

Post Lantern PL1
Post Lantern PL2
Post Lantern PL10
Post Lantern PL22

Landscape Light LV1
Landscape Light LV2
Landscape Light LV10
Landscape Light LV11

短い名前が最初にソートされると思いますか?

結果を自然に並べ替えたい: アルファベット順で、数値も自然な順序で。私が試してみました:

ORDER by CAST(`product_name` AS DECIMAL), product_name
...
ORDER by product_name+0

短い方の名前は、アルファベット順では後ろにあるにもかかわらず、最初にソートされます。最後の部分の数字は、番号順に並べる必要があります。

4

1 に答える 1

0

これがあなたが探していることをする長いクエリです。ただし、パフォーマンスについてはよくわかりません。確認するために、いくつかのレコードでいくつかのテストを行うこともできます。

SELECT
    *
    ,SUBSTRING(
        REVERSE(CAST(REVERSE(CONCAT(`product_name`,'8')) AS UNSIGNED)),1,
        CHARACTER_LENGTH(
            REVERSE(CAST(REVERSE(CONCAT(`product_name`,'8')) AS UNSIGNED))
        )-1
    ) AS 'numericVal'
FROM `some_table`
ORDER BY
    SUBSTRING(`product_name`,1,CHAR_LENGTH(`product_name`)-CHAR_LENGTH(`numericVal`)),
    CAST(`numericVal` AS UNSIGNED INTEGER)

関数の8は、ゼロで終わる数値用にあります。CONCAT()それ以外の場合、たとえば文字列 "etc30"を逆にして数値を解析すると、 03ではなく3になります。したがって、元に戻すと、 30ではなく3が生成されます。

関数内のこれら2つの8CONCAT()は、任意の1桁(ゼロを除く)で変更できます。

[編集2]

内訳は次のとおりです。

# Example record "Post Lantern PL10"...
SELECT
    *
    ,SUBSTRING(                                         # 5a) substring of this is calculated
        REVERSE(                                        # 4) gets re-reversed into "108"
            CAST(                                       # 3) gets casted into an integer so "801" part is parsed
                REVERSE(                                # 2) gets reversed: "801LP nretnaL tsoP"
                    CONCAT(`product_name`,'8')          # 1) is concatenated with an 8: "Post Lantern PL108"
                )
            AS UNSIGNED)
        ),
        1,                                              # 5b) from the first character (index is 1 for this in SQL)
        CHARACTER_LENGTH(                               # 5c) and the length is recalculated (steps 1-4 repeated)
            REVERSE(
                CAST(
                    REVERSE(
                        CONCAT(`product_name`,'8')
                    )
                AS UNSIGNED)
            )
        )-1                                             # 5d1) minus 1 because at the beginning we appended an 8 and we
                                                        # 5d2) want to get rid of it now, so we're dropping the last digit
    ) AS 'numericVal'
FROM `some_table`
ORDER BY                                                        # 6) order by
    SUBSTRING(`product_name`,                                   # 7a) first, substring `product_name`
        1,                                                      # 7b) from the first character
        CHAR_LENGTH(`product_name`)-CHAR_LENGTH(`numericVal`)   # 7c) with the total length - length of numeric part
    ),
    CAST(`numericVal` AS UNSIGNED INTEGER)                      # 8a) then, by the numeric part, which gets casted into
                                                                # 8b) an integer for accurate numeric ordering

[編集1]

(さまざまなデータを完全に制御するための)ベストショットは、 ( 「Landscape Light」のように)、(または「LV」のように)、(数値部分)のproduct_name3つの列に分割することだと思います。product_nameproduct_classproduct_version

于 2013-01-05T04:06:53.893 に答える