Home > Back-end >  Sql distinct group of rows
Sql distinct group of rows

Time:07-18

In sql i want get distict sets of rows : identical group for Characteristic and Value only one time :

The column Characteristic can range from one to 10

Table :

Name Characteristic Value
Mary eyes Blu
Mary hair blonde
Mary Sex Female
Jhon eyes Black
Jhon Hair Black
Jhon Sex Male
Jhon Nation Franch
Bill eyes Blu
Bill Hair Blond
Bill Sex Male
Will eyes Green
Will Hair Blond
Will Sex Male
Will Nation Spain
Lilly eyes Blu
Lilly Hair Blonde
Lilly Sex Female
mark eyes Black
mark Hair Black
mark Sex Male
mark Nation Franch
Anna eyes Blu
Anna Hair Blonde
Anna Sex Female
Antonio eyes Black
Antonio Hair Black
Antonio Sex Male
Antonio Nation Franch

The result that i want to achieve :

Group Characteristic Value
1 eyes Blu
1 Hair Blonde
1 Sex Female
2 eyes Black
2 Hair Black
2 Sex Male
2 Nation Franch
3 eyes Blu
3 Hair Blond
3 Sex Male
4 eyes Green
4 Hair Blode
4 Sex Male
4 Nation Spain

and finally if it's possible :

Name Characteristic Value Group
Mary eyes Blu 1
Mary Hair Blonde 1
Mary Sex Female 1
Jhon eyes Black 2
Jhon Hair Black 2
Jhon Sex Male 2
Jhon Nation Franch 2
Bill eyes Blu 3
Bill Hair Blond 3
Bill Sex Male 3
Will eyes Green 4
Will Hair Blond 4
Will Sex Male 4
Will Nation Spain 4
Lilly eyes Blu 1
Lilly Hair Blonde 1
Lilly Sex Female 1
mark eyes Black 2
mark Hair Black 2
mark Sex Male 2
mark Nation Franch 2
Anna eyes Blu 1
Anna Hair Blonde 1
Anna Sex Female 1
Antonio eyes Black 2
Antonio Hair Black 2
Antonio Sex Male 2
Antonio Nation Franch 2

CodePudding user response:

You can use STRING_AGG to join all the characteristics together, then use ROW_NUMBER and DENSE_RANK to count them. Then you re-join that back to the base table.

For your first query, you can do it like this.

SELECT
  Groups.GroupId,
  t.Characteristic,
  t.Value
FROM YourTable t
JOIN (
    SELECT
      t.Name,
      t.GroupDefinition,
      GroupId = DENSE_RANK() OVER (ORDER BY t.GroupDefinition),
      RowId = ROW_NUMBER() OVER (PARTITION BY t.GroupDefinition ORDER BY t.Name)
    FROM (
        SELECT
          t.Name,
          GroupDefinition = STRING_AGG(Characteristic   ':'   Value, '|')
              WITHIN GROUP (ORDER BY t.Characteristic)
        FROM YourTable t
        GROUP BY
          t.Name
    ) t
) Groups ON Groups.Name = t.Name
WHERE Groups.RowId = 1;

The second query is as follows.

SELECT
  Groups.GroupId,
  t.*
FROM YourTable t
JOIN (
    SELECT
      t.Name,
      t.GroupDefinition,
      GroupId = DENSE_RANK() OVER (ORDER BY t.GroupDefinition),
      RowId = ROW_NUMBER() OVER (PARTITION BY t.GroupDefinition ORDER BY t.Name)
    FROM (
        SELECT
          t.Name,
          GroupDefinition = STRING_AGG(Characteristic   ':'   Value, '|')
              WITHIN GROUP (ORDER BY t.Characteristic)
        FROM YourTable t
        GROUP BY
          t.Name
    ) t
) Groups ON Groups.Name = t.Name;

db<>fiddle

Another option would be to aggregate it into a JSON or XML format, then shred it back out without re-joining the base table.

  • Related