В SQL Server, как нумеровать совпадающие наборы данных в таблице? - PullRequest
0 голосов
/ 25 апреля 2018

Учитывая набор данных, показанный ниже, мне нужно иметь возможность получить значение в optionGroupNumber справа на основе значений в столбцах optionType & optionValue.Таким образом, для Порядка 1 опции, выбранные для клавиш детализации 1 и 2, одинаковы (зеленый оттенок), поэтому они получают значение optionGroup 1. Клавиша детализации 3 (синяя тень) имеет другой набор опций, чем 1 & 2,так что он получает 2 как optionGroupNumber.

Optionvalues произвольно вводятся пользователями, поэтому они могут быть любыми.

Как это можно сделать с помощью T-SQL?

enter image description here

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Попробуйте этот запрос ...

WITH cte (detailkey, alloptionvalues) 
     AS (SELECT detailkey, 
                allOptionValues = Stuff((SELECT N', ' + optionvalue 
                                         FROM   tablename AS subTbl 
                                         WHERE  subTbl.detailkey = mainTbl.detailkey 
                                         FOR xml path(N'')), 1, 2, N'') 
         FROM   tablename AS mainTbl 
         GROUP  BY detailkey) 

SELECT tablename.orderno, 
       tablename.detailkey, 
       tablename.style, 
       tablename.[format], 
       tablename.leather, 
       tablename.optiontype, 
       tablename.optionvalue, 
       tablename.optionadditionalinfo, 
       tmpQueryTbl.optionGroupNumber 
FROM   tablename 
       INNER JOIN (SELECT *, 
                          Dense_rank() OVER(ORDER BY alloptionvalues) AS optionGroupNumber 
                   FROM   cte) tmpQueryTbl 
               ON tablename.detailkey = tmpQueryTbl.detailkey 

Результат

+---------+-----------+-------+--------+---------+-----------------------------------+-------------+----------------------+-------------------+
| orderno | detailkey | style | format | leather |            optiontype             | optionvalue | optionadditionalinfo | optionGroupNumber |
+---------+-----------+-------+--------+---------+-----------------------------------+-------------+----------------------+-------------------+
|       1 |         1 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING               | BLIND       | NULL                 |                 1 |
|       1 |         1 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING FOIL          | BLIND       | NULL                 |                 1 |
|       1 |         1 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING FOIL POSITION | BLC         | NULL                 |                 1 |
|       1 |         1 | WJ7   | MRBL   | PYT     | ETA FOR MATERIALS                 | 4/25/2018   | NULL                 |                 1 |
|       1 |         2 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING               | BLIND       | NULL                 |                 1 |
|       1 |         2 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING FOIL          | BLIND       | NULL                 |                 1 |
|       1 |         2 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING FOIL POSITION | BLC         | NULL                 |                 1 |
|       1 |         2 | WJ7   | MRBL   | PYT     | ETA FOR MATERIALS                 | 4/25/2018   | NULL                 |                 1 |
|       1 |         3 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING               | SILVER      | NULL                 |                 2 |
|       1 |         3 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING FOIL          | SILVER      | NULL                 |                 2 |
|       1 |         3 | WJ7   | MRBL   | PYT     | ADDITIONAL STAMPING FOIL POSITION | FLR         | NULL                 |                 2 |
|       1 |         3 | WJ7   | MRBL   | PYT     | ETA FOR MATERIALS                 | 4/25/2018   | NULL                 |                 2 |
+---------+-----------+-------+--------+---------+-----------------------------------+-------------+----------------------+-------------------+

Демонстрация: http://sqlfiddle.com/#!18/0b419/1/0

Чтобы обновить данные, используйте этот запрос SQL

WITH cte (detailkey, alloptionvalues) 
     AS (SELECT detailkey, 
                allOptionValues = Stuff((SELECT N', ' + optionvalue 
                                         FROM   tablename AS subTbl 
                                         WHERE  subTbl.detailkey = mainTbl.detailkey 
                                         FOR xml path(N'')), 1, 2, N'') 
         FROM   tablename AS mainTbl 
         GROUP  BY detailkey) 

UPDATE tablename 
SET    tablename.optiongroupnumber = resultSet.optiongroupnumber 

FROM   (SELECT tablename.orderno, 
               tablename.detailkey, 
               tablename.style, 
               tablename.[format], 
               tablename.leather, 
               tablename.optiontype, 
               tablename.optionvalue, 
               tablename.optionadditionalinfo, 
               tmpQueryTbl.optiongroupnumber 
        FROM   tablename 
               INNER JOIN (SELECT *, 
                                  Dense_rank() 
                                    OVER( 
                                      ORDER BY alloptionvalues) AS 
                                  optionGroupNumber 
                           FROM   cte) tmpQueryTbl 
                       ON tablename.detailkey = tmpQueryTbl.detailkey) resultSet 
-- use where with PK columns  
WHERE  tablename.orderno = resultSet.orderno 
       AND tablename.detailkey = resultSet.detailkey 
       AND tablename.optiontype = resultSet.optiontype 
       AND tablename.optionvalue = resultSet.optionvalue 
       AND tablename.style = resultSet.style 
       AND tablename.[format] = resultSet.[format] 
       AND tablename.leather = resultSet.leather 
0 голосов
/ 26 апреля 2018

Понятия не имею, насколько это будет эффективно.Похоже, он работает с небольшим количеством тестовых данных.

with X as (
    select
        orderNo, detailKey, optionType, optionValue,
        count(*) over (partition by orderNo, detailKey) as optionCnt,
        dense_rank() over (partition by orderNo order by optionType, optionValue) as tag
    from O
), Y as (
    select
        coalesce(x1.orderNo, x2.orderNo) as orderNo,
        x1.detailKey as detailKey1, x2.detailKey as detailKey2,
        row_number() over (partition by coalesce(x1.orderNo, x2.orderNo) 
                           order by x1.detailKey, x2.detailKey) as rnk
    from X x1 full outer join X x2
        on x2.orderNo = x1.orderNo and x2.detailKey > x1.detailKey and x2.tag = x1.tag
    group by coalesce(x1.orderNo, x2.orderNo), x1.detailKey, x2.detailKey
    having count(x1.orderNo) = min(x1.optionCnt) and count(x2.orderNo) = min(x2.optionCnt)
), Z as (
    select orderNo, detailKey,
        coalesce('Merge with ' + cast(mergeKey as varchar(4)), 'Cannot merge') as note,
        dense_rank() over (partition by orderNo
                           order by coalesce(mergeKey, detailKey)) as optionGroupNumber
    from
        (select distinct orderNo, detailKey from O) o
        outer apply (
            select min(y.detailKey1) as mergeKey from Y y
            where y.orderNo = o.orderNo and o.detailKey in (y.detailKey1, y.detailKey2)
        ) as m
)
select * from Z;

Вот краткий обзор:

  1. Получите количество опций на detailKey.Пронумеруйте каждую пару настроек параметров.
  2. Объедините наборы параметров, чтобы увидеть, полностью ли они совпадают.
  3. Сократите наборы совпадений до одного канонического представителя.

http://rextester.com/GEUD41256

0 голосов
/ 26 апреля 2018

Требование сложно понять, поэтому я буду основывать свой ответ на этом:

Учитывая набор данных, показанный ниже, мне нужно иметь возможность получить значение в optionGroupNumber дляверно, на основе значений в столбцах optionType & optionValue.

Допустим, у нас была таблица с животными и цветами, и мы хотели создать номер группы на основе животных того же типа и цвета.Мы бы сделали это с помощью RANK () следующим образом:

-- sample data
DECLARE @sometable TABLE (someId int identity, pet varchar(20), color varchar(20));
INSERT @sometable (pet, color)
VALUES ('cat','blue'),('pig','green'),('cat','yellow'),('pig','green'),('cat','yellow'),
('cat','blue'),('dog','black'),('dog','white'),('pig','green'),('dog','black');

-- group by pet and color
SELECT *, OptionGroupNumber = DENSE_RANK() OVER (ORDER BY pet, color)
FROM @sometable;

Результат:

someId      pet                  color                OptionGroupNumber
----------- -------------------- -------------------- --------------------
1           cat                  blue                 1
6           cat                  blue                 1
3           cat                  yellow               2
5           cat                  yellow               2
10          dog                  black                3
7           dog                  black                3
8           dog                  white                4
9           pig                  green                5
4           pig                  green                5
2           pig                  green                5

Обратите внимание, как работает группировка:

enter image description here

Чтобы обновить существующий столбец, вы должны взять эту логику и применить ее к выражению UPDATE, например:

-- sample data
DECLARE @sometable TABLE 
  (someId int identity, pet varchar(20), color varchar(20), OptionGroupNumber int);

INSERT @sometable (pet, color)
VALUES ('cat','blue'),('pig','green'),('cat','yellow'),('pig','green'),('cat','yellow'),
('cat','blue'),('dog','black'),('dog','white'),('pig','green'),('dog','black');

WITH generateOptionGroupNumber AS
(
  SELECT *, newOptionGroupNumber = DENSE_RANK() OVER (ORDER BY pet, color)
  FROM @sometable
)
UPDATE generateOptionGroupNumber
SET OptionGroupNumber = newOptionGroupNumber

SELECT * 
FROM @sometable
ORDER BY OptionGroupNumber;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...