3

情報を取得するためにクエリを作成するのに助けが必要ですが、それを書くのに問題があります。

[table_People]
int id
var name

[table_Tools]
int id
var name

[table_Activity1]
int person_id
int tool_id
date delivery_date

[table_Activity2]
int person_id
int tool_id
date installation_date

クエリは、すべての人のリストと、アクティビティ 1 または 2 (2 つの間で発生した最新のアクティビティ) で使用された最新のツールの名前を返す必要があります。

SELECT
    people.id   AS personId,
    people.name AS personName,
    (
        SELECT
            tools.name AS toolName
        FROM
            activity1
        JOIN
            tools ON tools.id=activity1.tool_id
        WHERE
            activity1.id=people.id
        UNION ALL
        SELECT
            tools.name AS toolName
        FROM
            activity2
        JOIN
            tools ON tools.id=activity2.tool_id
        WHERE
            activity2.id=people.id
        ORDER BY
            installationDate,deliveryDate
    ) AS toolName
FROM
    people
ORDER BY
    people.name
ASC

私が抱えている問題は、列名が異なるためエラーが発生するため、日付 (配送またはインストール) で並べ替えることができないことです。

4

7 に答える 7

4

サブクエリで UNION を使用すると、派生一時テーブルが作成されます。選択されていない列は結果セットに含まれないため、SELECT 句に含まれていない列に対して ORDER を実行することはできません。

UNION を使用する場合、SELECT 句で使用される最初の列名が結果セットで使用されます (エイリアスを使用することもできますが、エイリアスに似ています)。

SELECT 句で必ず列に名前を付けてください。

サブクエリを単一の行に制限するには、LIMIT 句も必要です。

SELECT
    people.id   AS personId,
    people.name AS personName,
    (
        SELECT
            tools.name AS toolName, delivery_date
        FROM
            activity1
        JOIN
            tools ON tools.id=activity1.tool_id
        WHERE
            activity1.id=people.id
        UNION ALL
        SELECT
            tools.name AS toolName, installation_date
        FROM
            activity2
        JOIN
            tools ON tools.id=activity2.tool_id
        WHERE
            activity2.id=people.id
        ORDER BY
            deliveryDate
        LIMIT 1
    ) AS toolName
FROM
    people
ORDER BY
    people.name
ASC

この問題を説明するためのより簡単な例を次に示します。

SELECT fish FROM sea
UNION
SELECT dog FROM land
ORDER BY fish

以下と同じです:

SELECT fish AS animal FROM sea
UNION
SELECT dog AS animal FROM land
ORDER BY animal

結果は派生一時テーブルに入れられ、列には好きな名前を付けることができますが、使用する最初の名前は固執します。

于 2012-05-15T21:42:31.380 に答える
2

私の解決策は、サブクエリでユニオンをまとめてから、それらによって注文します。最初の行のみが必要なため、制限句が必要です (または、Oracle では rownum = 1、MSSQL では top 1)。

SELECT people.id   AS personId,
       people.name AS personName, 
       (SELECT toolname
        FROM ((SELECT tools.name AS toolName, delivery_date as thedate
               FROM activity1 a
               WHERE a.PersonId = people.id
              ) union all
              (SELECT tools.name AS toolName, installation_date as thedate
               FROM activity2 a
               WHERE a.PersonId = people.id
              )
             ) a join
             tools t
             on a.toolsid = t.toolsid
        order by 2 desc
        limit 1
       ) AS toolName
FROM people
ORDER BY people.name ASC

クエリを簡素化するために、ツールへの最も内側の結合も削除しました。

于 2012-05-15T21:13:59.043 に答える
0

people.id を person_id として、people.name を person_name として、tools.name を toolsname として table_people から選択します。 person_id else act1.person_id end as recent_most_person_id from table_activity1 act1 内部結合 table_activity2 act2 on act1.person_id=act2.person_id)X on people.id=X.recent_most_person_id 内部結合 table_tools tools on tools.id=X.recent_most_tool_id

于 2012-05-16T04:27:14.127 に答える
0

MySQL のバージョン (よりコンパクトなコードを取得できる可能性があります):

Select * from 
(
  Select toolName, person_id, Max(TargetDate) as MaxDate
  From
        (
            SELECT tools.name AS toolName, activity1.person_id, activity1.delivery_date as targetDate
            FROM
                activity1
            JOIN
                tools ON tools.id=activity1.tool_id
            UNION ALL
            SELECT
                tools.name AS toolName, activity2.person_id, activity2.installation_date as TargetDate
            FROM
                activity2
            JOIN
                tools ON tools.id=activity2.tool_id
        )
 Group by toolName, person_id

) preselect
    join
    (
    Select toolName, person_id, Max(TargetDate)
    From
            (
                SELECT tools.name AS toolName, activity1.person_id, activity1.delivery_date as targetDate
                FROM
                    activity1
                JOIN
                    tools ON tools.id=activity1.tool_id
                UNION ALL
                SELECT
                    tools.name AS toolName, activity2.person_id, activity2.installation_date as TargetDate
                FROM
                    activity2
                JOIN
                    tools ON tools.id=activity2.tool_id
            )) result on result.toolName = preselect.toolName and result.person_id = preselect.person_id and result.TargetDate = preselect.MaxDate
于 2012-05-15T21:21:16.090 に答える
0
SELECT
    p.id             AS person_id
  , p.name           AS person_name
  , CASE WHEN COALESCE(a1.delivery_date, '1000-01-01')
              > COALESCE(a2.installation_date, '1000-01-01')
           THEN t1.name
           ELSE t2.name
    END              AS tool_name
FROM 
    People AS p
  LEFT JOIN 
    Activity1 AS a1
        ON (a1.tool_id, a1.delivery_date) =
           ( SELECT tool_id, delivery_date
             FROM Activity1 AS a
             WHERE a.person_id = p.id
             ORDER BY delivery_date DESC
             LIMIT 1
           )
  LEFT JOIN 
    Tools AS t1
        ON t1.id = a1.tool_id
  LEFT JOIN 
    Activity2 AS a2
        ON (a2.tool_id, a2.installation_date) =
           ( SELECT tool_id, installation_date
             FROM Activity2 AS a
             WHERE a.person_id = p.id
             ORDER BY installation_date DESC
             LIMIT 1
           )
  LEFT JOIN 
    Tools AS t2
        ON t2.id = a2.tool_id
于 2012-05-15T22:05:54.347 に答える
0

の後に列を指定しないと列をソートできませんselect

例えば:

select name from people order by name

select a1.delivery_date, t.name from activity1 a1, tools t 
order by a1.delivery_date,t.name

プロジェクション用に選択されたすべての列も、定義でorder by定義する必要があります。あなたの例では、両方の select ステートメントが取っているだけtools.name as toolnameですが、他の列で並べ替えたいと考えています。

于 2012-05-15T20:59:31.377 に答える
0

行う

SELECT
    people.id   AS personId,
    people.name AS personName,
    IF (
        (SELECT
            deliveryDate AS dDate
        FROM
            activity1
        WHERE
            person_id=personId) --assuming you have only one row returned here, else limit by some condition
        >
        (SELECT
            installationDate AS iDate
         FROM
            activity2
         WHERE
            person_id=personId) --assuming you have only one row returned here, else limit by some condition
         , (SELECT
                tools.name AS toolName
            FROM
                activity1
            JOIN
                tools ON tools.id=activity1.tool_id
            WHERE
                activity1.person_id=personId)
         , (SELECT
                tools.name AS toolName
            FROM
                activity2
            JOIN
                tools ON tools.id=activity2.tool_id
            WHERE
                activity2.person_id=personId)
           ) AS toolName
FROM
    people        
ORDER BY
    people.name
ASC

このクエリは、アクティビティ テーブルに 1 人あたりのレコードしかないことを前提としています。さらにある場合は、合計最大条件に基づいて選択結果セットを制限する必要があります。これはあなただけが知っています。

于 2012-05-15T21:10:04.787 に答える