Фильтрация результатов, возвращаемых SQL-запросом - PullRequest
0 голосов
/ 28 ноября 2011

Я изо всех сил пытался решить это весь день - это кажется довольно простым, но я должен что-то упустить!

У меня есть запрос, который возвращает некоторые данные, два столбца, которые он возвращает, -"PackageWeight" и "PackageGroup".По сути, я хочу отфильтровать эти данные, чтобы показать только одну строку для каждой «PackageGroup» - это должна быть строка с наибольшим значением в столбце «PackageWeight».

Это кажется простым, но я просто могу 'заставить его работать в SQL Server, используя комбинацию TOP 1 и GROUP BY.Я должен что-то упустить!

    SELECT VendorID, PackageID, PackageWeight, PackageGroup
  FROM (SELECT VendorID, COUNT(*) AS qty
          FROM VendorServices
         GROUP BY VendorID
       ) cs
  JOIN (SELECT PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup, COUNT(*) AS qty
          FROM PackageServices
          JOIN lookupPackages ON PackageServices.PackageID = lookupPackages.PackageID
          GROUP BY PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup
       ) ps ON cs.qty >= ps.qty
  WHERE (SELECT COUNT(*)
          FROM VendorServices cs2
          JOIN PackageServices ps2 ON cs2.ServiceTypeID = ps2.ServiceID
         WHERE cs2.VendorID = cs.VendorID
           AND ps2.PackageID = ps.PackageID
       ) = ps.qty

Этот запрос возвращает мне полный набор данных, который мне нужно отфильтровать.Однако мои попытки пока не увенчались успехом: (

Любая помощь высоко ценится!

РЕДАКТИРОВАТЬ - Спасибо авторам ниже, пока у меня есть следующий запрос:

with result_cte as
(
SELECT VendorID, PackageID, PackageWeight, PackageGroup,
    RANK() over (partition by PackageGroup order by PackageWeight desc) as [rank]
FROM (SELECT VendorID, COUNT(*) AS qty
    FROM VendorServices
    GROUP BY VendorID
    ) cs
JOIN (SELECT PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup, COUNT(*) AS qty
    FROM PackageServices
    JOIN lookupPackages ON PackageServices.PackageID = lookupPackages.PackageID
    GROUP BY PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup
    ) ps ON cs.qty >= ps.qty
WHERE (SELECT COUNT(*)
    FROM VendorServices cs2
    JOIN PackageServices ps2 ON cs2.ServiceTypeID = ps2.ServiceID
    WHERE cs2.VendorID = cs.VendorID
    AND ps2.PackageID = ps.PackageID
    ) = ps.qty
)

select *
from result_cte
WHERE [rank] = 1
ORDER BY VendorID

Пока все хорошо. Я все же посмотрю на оператор APPLY, предложенный @gbn, так как он для меня новый - и мне все еще нужно провести некоторое тестирование, чтобы убедиться, что этот запрос работает на 100%.времени. Однако начальные показания хороши!

Спасибо всем, кто уже внес свой вклад.

EDIT 2 - К сожалению, после заполнения базы данных большим количеством примеров данныхэтот запрос не сработал. Кажется, что пропущены некоторые записи.

Возможно, мне нужно объяснить немного больше о том, что здесь происходит. Данные, возвращаемые моим исходным запросом, перечисляют каждого клиента в системевместе с производным PackageID (рассчитанным по этому запросу), а также весом и группой, назначенными этому Package в таблице поиска.

Мне нужно отфильтровать исходную таблицу результатов, чтобы не получить мобольше, чем один пакет из каждой группы, для каждого клиента (каждый клиент может иметь пакет из одной или нескольких групп, но может не иметь пакет из каждой группы)

Я рассмотрю этот вопрос более свежим завтра, так какЯ думаю, что могу оказаться в ситуации «Не вижу леса за деревьями»!

Спасибо всем.

Ответы [ 4 ]

1 голос
/ 28 ноября 2011

Можете ли вы попробовать это?Это не пуленепробиваемо, если у вас есть несколько записей с одинаковым весом в одной группе.Есть и другие способы справиться с этим.

with result_cte as
(
SELECT VendorID, PackageID, PackageWeight, PackageGroup
FROM (SELECT VendorID, COUNT(*) AS qty
    FROM VendorServices
    GROUP BY VendorID
    ) cs
JOIN (SELECT PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup, COUNT(*) AS qty
    FROM PackageServices
    JOIN lookupPackages ON PackageServices.PackageID = lookupPackages.PackageID
    GROUP BY PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup
    ) ps ON cs.qty >= ps.qty
WHERE (SELECT COUNT(*)
    FROM VendorServices cs2
    JOIN PackageServices ps2 ON cs2.ServiceTypeID = ps2.ServiceID
    WHERE cs2.VendorID = cs.VendorID
    AND ps2.PackageID = ps.PackageID
    ) = ps.qty
)

select *
from result_cte
where result_cte.PackageWeight = (select top 1 highestweight.PackageWeight from result_cte highestweight
                                where highestweight.PackageGroup = result_cte.PackageGroup
                                order by highestweight.PackageWeight desc)

Или вы можете сделать это:

with result_cte as
(
SELECT VendorID, PackageID, PackageWeight, PackageGroup,
    ROW_NUMBER() over (partition by PackageGroup order by PackageWeight desc) as [row]
FROM (SELECT VendorID, COUNT(*) AS qty
    FROM VendorServices
    GROUP BY VendorID
    ) cs
JOIN (SELECT PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup, COUNT(*) AS qty
    FROM PackageServices
    JOIN lookupPackages ON PackageServices.PackageID = lookupPackages.PackageID
    GROUP BY PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup
    ) ps ON cs.qty >= ps.qty
WHERE (SELECT COUNT(*)
    FROM VendorServices cs2
    JOIN PackageServices ps2 ON cs2.ServiceTypeID = ps2.ServiceID
    WHERE cs2.VendorID = cs.VendorID
    AND ps2.PackageID = ps.PackageID
    ) = ps.qty
)

select *
from result_cte
where [row] = 1
0 голосов
/ 29 ноября 2011

Благодаря посту Eric.K.Yung - я наконец-то решил это, используя его запрос, но добавив VendorID (фактически CustomerID) к части запроса 'partition by' Это гарантировало, что пакеты были возвращены для всех клиентов.

Спасибо всем, кто внес свой вклад. Последний запрос:

with result_cte as
(
SELECT VendorID, PackageID, PackageWeight, PackageGroup,
    ROW_NUMBER() over (partition by PackageGroup, VendorID order by PackageWeight desc) as [row]
FROM (SELECT VendorID, COUNT(*) AS qty
    FROM VendorServices
    GROUP BY VendorID
    ) cs
JOIN (SELECT PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup, COUNT(*) AS qty
    FROM PackageServices
    JOIN lookupPackages ON PackageServices.PackageID = lookupPackages.PackageID
    GROUP BY PackageServices.PackageID, lookupPackages.PackageWeight, lookupPackages.PackageGroup
    ) ps ON cs.qty >= ps.qty
WHERE (SELECT COUNT(*)
    FROM VendorServices cs2
    JOIN PackageServices ps2 ON cs2.ServiceTypeID = ps2.ServiceID
    WHERE cs2.VendorID = cs.VendorID
    AND ps2.PackageID = ps.PackageID
    ) = ps.qty
)

select *
from result_cte
where [row] = 1
0 голосов
/ 28 ноября 2011

Вы можете использовать функцию MAX:

SELECT * FROM #one
lbs groups
5   0
4   0
1   0
9   1
2   1     

SELECT groups,MAX(lbs)
FROM #one
GROUP BY groups

groups  (No column name)
0   5
1   9
0 голосов
/ 28 ноября 2011

Готовы ли вы принять одного произвольного поставщика и PackageID, если несколько групп имеют одинаковый максимальный вес в группе? Если все в порядке, просто добавьте к ним совокупность, а также PackageWeight:

SELECT max(VendorID), max(PackageID), max(PackageWeight), PackageGroup
...
GROUP BY PackageGroup

В противном случае вам нужно будет сделать как Е.Ю. предлагает и выполнить вложенный запрос, чтобы сначала найти максимальный вес на группу и обработать дубликаты, если таковые имеются, самостоятельно.

...