2

すべてのカテゴリ、サブカテゴリを選択し、サブカテゴリに属する​​ビジネスの数を数えたいです。これは私が使用しているSQlクエリです。

SELECT
    c.id, 
    c.name,
    c.slug,
    sc.id,
    sc.name,
    sc.slug,
    COUNT(bsc.id) AS business_count
FROM 
    fi_category c
LEFT JOIN 
    fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL) 
LEFT JOIN 
    fi_business_subcategory bsc ON sc.id = bsc.subcategory_id AND (bsc.deleted_at IS NULL) 
WHERE 
    (c.deleted_at IS NULL) 
GROUP BY 
    c.id, sc.id

ただし、やりたいことがもっとあります。business_countは、所属する都市に応じてフィルタリングする必要があります。つまり、最終的にはすべてのカテゴリ、サブカテゴリを選択する必要がありますが、business_countには、のような句が必要WHERE city.id = 1です。これには、countをサブクエリとして使用する必要があると思います。私はそれを理解することができませんでした。

以下は、からfi_business_subcategoryへの関係構造fi_cityです。

1)fi_business_subcategory

+----+----------------+-------------+
| id | subcategory_id | business_id |
+----+----------------+-------------+

2)fi_business

+----+---------+-----------+
| id | name    | suburb_id |
+----+---------+-----------+

3)fi_suburb

+-----+--------+---------+
| id  | name   | city_id |
+-----+--------+---------+

4)fi_city

+----+--------+
| id | name   |
+----+--------+

私はこのようなことを試みましたが、これはうまくいかないようです

SELECT
    c.id, 
    c.name,
    c.slug,
    sc.id,
    sc.name,
    sc.slug,
    bsc.business_count
FROM 
    fi_category c
LEFT JOIN 
    fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL) 
LEFT JOIN (
    SELECT 
        COUNT(business_id) t1.business_count, t1.subcategory_id 
    FROM
        fi_business_subcategory t1
    LEFT JOIN
        fi_business t2 ON t2.id = t1.business_id
    LEFT JOIN
        fi_suburb t3 ON t3.id = t2.suburb_id
    LEFT JOIN
        fi_city t4 ON t4.id = t3.city_id
    WHERE
        t4.id = 1
    GROUP BY
        t1.subcategory_id
) bsc ON sc.id = bsc.subcategory_id AND (bsc.deleted_at IS NULL)
WHERE 
    (c.deleted_at IS NULL) 
GROUP BY 
    c.id, sc.id

クエリを作成して、必要なものを実現するにはどうすればよいですか?

4

3 に答える 3

2

サブクエリを使用する場合、2番目のクエリを可能な限り小さな変更で表現する正しい方法は次のとおりです。

SELECT
    c.id, 
    c.name,
    c.slug,
    sc.id,
    sc.name,
    sc.slug,
    IFNULL(bsc.business_count, 0)
          -- turn NULL from left join into 0
FROM 
    fi_category c
LEFT JOIN 
    fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL) 
LEFT JOIN (
    SELECT 
        COUNT(*) business_count, t1.subcategory_id
          -- removed table name from alias name,
          -- and improved performance by simply counting rows
    FROM
        fi_business_subcategory t1
    LEFT JOIN
        fi_business t2 ON t2.id = t1.business_id
    LEFT JOIN
        fi_suburb t3 ON t3.id = t2.suburb_id
    LEFT JOIN
        fi_city t4 ON t4.id = t3.city_id
    WHERE
        t4.id = 1 AND (t1.deleted_at IS NULL)
          -- check deletion in subquery for performance
    GROUP BY
        t1.subcategory_id
) bsc ON sc.id = bsc.subcategory_id
          -- no longer need to check deletion here
WHERE 
    (c.deleted_at IS NULL) 
GROUP BY 
    c.id, sc.id

ここでフィドル。

于 2012-09-14T06:37:12.293 に答える
2

サブクエリを使用する必要がある理由はわかりません。私はあなたが単純に単一の括弧で囲まれたテーブルファクターにfi_business結合することができると信じています。fi_business_subcategory

SELECT
    c.id, 
    c.name,
    c.slug,
    sc.id,
    sc.name,
    sc.slug,
    COUNT(bsc.id) AS business_count
FROM
    fi_category c
LEFT JOIN
    fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
LEFT JOIN (
        fi_business b
    INNER JOIN
        fi_business_subcategory bsc ON b.id = bsc.business_id AND (bsc.deleted_at IS NULL)
    INNER JOIN
        fi_suburb su ON su.id = b.suburb_id AND su.city_id = 1
    ) ON sc.id = bsc.subcategory_id
WHERE 
    (c.deleted_at IS NULL) 
GROUP BY 
    c.id, sc.id

これがテーブル構造に有効なSQLであることを確認しました。フィドルにまだデータが含まれていなくても、目的の結果が得られる可能性は高いと思います。結合で括弧を使用できる場所の詳細については、JOIN構文のマニュアルを参照してください。

また、すべての結合を左結合にする必要があるかどうかを自問することもできます。内部結合を使用して物事を書くのははるかに簡単です。

結合は左から右に実行されるため、最初に内部結合を実行し、次に一連の結合を実行する場合があります。これにより、括弧が回避されます。

SELECT
    c.id cat_id,
    c.name cat_name,
    c.slug cat_slug,
    sc.id sub_id,
    sc.name sub_name,
    sc.slug sub_slug,
    COUNT(bsc.id) AS business_count
FROM
    fi_business b
INNER JOIN
    fi_business_subcategory bsc ON b.id = bsc.business_id
    AND (b.deleted_at IS NULL) AND (bsc.deleted_at IS NULL)
INNER JOIN
    fi_suburb su ON su.id = b.suburb_id AND su.city_id = 1
RIGHT JOIN
    fi_subcategory sc ON sc.id = bsc.subcategory_id
RIGHT JOIN
    fi_category c ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
WHERE
    (c.deleted_at IS NULL)
GROUP BY
    c.id, sc.id
于 2012-09-14T05:52:29.477 に答える
1

これを試して

select 
    c.id,
    c.name,
    count(sc.name) as Count
from fi_category as c
left join fi_subcategory as sc on sc.category_id = c.id
left join fi_business_subcategory as  fbs on fbs.subcategory_id = sc.id
inner join (
select 
    fb.name,
    fs.id,
    fs.city_id

from fi_business as fb 
inner join fi_suburb as fs on fs.id = fb.suburb_id
where fs.city_id = 1



) as  fb on fb.id = fbs.business_id
group by c.id
于 2012-09-14T06:48:28.863 に答える