SQL仅检索具有多个联接的查询中的最小值

时间:2013-11-13 17:00:21

标签: sql sql-server

假设我有一个跨三个表的多个连接的查询:

SELECT
    main_data.id,
    main_data.dt,
    main_data.seq_num,
    main_data.sale_amt,
    main_data.sale_cd,
    promo.promo_cd,
    payment.card,
    payment.priority
FROM
    main_data
INNER JOIN promo
    ON promo.id = main_data.id
    AND main_data.dt >= promo.start_dt
    AND main_data.dt <= promo_end_dt
INNER JOIN payment
    ON payment.sale_cd = main_data.sale_cd
    AND payment.card = main_data.card
WHERE 
    main_data.dt BETWEEN '2013-10-12' AND '2013-10-12'

基本上,销售额与付款方式(payment)和促销(promo)相关联。将促销代码映射到符合条件的付款(一对多关系)存在一些问题。

此时,main-data可能存在重复记录。因此,我需要使用具有最低值的payment.priority。如何仅提取该字段的最低值的行?我尝试将其嵌套为子查询,但无法使其正常工作。数据库本身是完全静态的,我无法以任何方式更改架构。

3 个答案:

答案 0 :(得分:1)

你可以试试这个。 row_number函数通过sale_cd对PAYMENT表中的项目进行分组,然后按优先级asc对条目进行排序。因此,row_num ='1'应该为您提供按sale_cd分组的优先级的最低值。

WITH CTE AS (CARD, PRIORITY, SALE_CD, ROW_NUM)
AS
(
  SELECT CARD
         , PRIORITY
         , SALE_CD
         , ROW_NUMBER() OVER(PARTITION BY SALE_CD ORDER BY PRIORITY ASC) AS ROW_NUM
  FROM PAYMENT
)

SELECT
    main_data.id,
    main_data.dt,
    main_data.seq_num,
    main_data.sale_amt,
    main_data.sale_cd,
    promo.promo_cd,
    CTE.card,
    CTE.priority
FROM
    main_data
INNER JOIN promo
    ON promo.id = main_data.id
    AND main_data.dt >= promo.start_dt
    AND main_data.dt <= promo_end_dt
INNER JOIN CTE CTE
    ON CTE.sale_cd = main_data.sale_cd
    AND CTE.card = main_data.card
WHERE 
    main_data.dt BETWEEN '2013-10-12' AND '2013-10-12'
    AND CTE.ROW_NUM = '1'

答案 1 :(得分:1)

您已经提到过,作为主要属性会给出重复项,所以我假设它们是GROUP BY列

WITH A AS
(
SELECT
    main_data.id,
    main_data.dt,
    main_data.seq_num,
    main_data.sale_amt,
    main_data.sale_cd,
    promo.promo_cd,
    payment.card,
    payment.priority
    , ROW_NUMBER() OVER(PARTITION BY main_data.id, main_data.dt, main_data.seq_num,   main_data.sale_amt, main_data.sale_cd ORDER BY payment.priority) AS RN
FROM
    main_data
INNER JOIN promo
    ON promo.id = main_data.id
    AND main_data.dt >= promo.start_dt
    AND main_data.dt <= promo_end_dt
INNER JOIN payment
    ON payment.sale_cd = main_data.sale_cd
    AND payment.card = main_data.card
WHERE 
    main_data.dt BETWEEN '2013-10-12' AND '2013-10-12'
)

SELECT * FROM A 
WHERE RN = 1

答案 2 :(得分:0)

SELECT
main_data.id,
main_data.dt,
main_data.seq_num,
main_data.sale_amt,
main_data.sale_cd,
promo.promo_cd,
payment.card,
min(payment.priority)
FROM
main_data
INNER JOIN promo
ON promo.id = main_data.id
AND main_data.dt >= promo.start_dt
AND main_data.dt <= promo_end_dt
INNER JOIN payment
ON payment.sale_cd = main_data.sale_cd
AND payment.card = main_data.card
WHERE 
main_data.dt BETWEEN '2013-10-12' AND '2013-10-12'
group by main_data.id,
main_data.dt,
main_data.seq_num,
main_data.sale_amt,
main_data.sale_cd,
promo.promo_cd,
payment.card