SQL Self Join без двойного перекрестного результата

-4

Я ищу решение с часами, но кошка его получит.

Моя таблица:

ID         name          value1      value2
1          Meyer         20          _
2          Schmitt       20          _
3          Berger        _           20
4          Chief         _           20

мой запрос:

SELECT A.ID, A.name AS nameA, B.name AS nameB, A.value1 
FROM table AS A INNER JOIN table AS B
ON A.value1 = B.value2

результат:

ID      nameA      nameB       value1
1       Meyer      Berger      20
1       Meyer      Chief       20
2       Schmitt    Berger      20
2       Schmitt    Chief       20  

Это должно выглядеть так:

ID      nameA       nameB      value1
1       Meyer       Berger     20
2       Schmitt     Chief      20

Как я могу получить этот результат?

Я также попробовал GROUP BY A.name, но получил неправильный результат:

ID       nameA      nameB     value1
1        Meyer      Berger    20
2        Schmitt    Berger    20
  • 0
    Что именно вы пытаетесь сделать здесь? Вы, вероятно, должны прочитать о нормализации базы данных.
  • 3
    Я не понимаю, как вы относитесь к записям. Если все значения value1 и value2 равны 20, как вы решаете, что «Meyer» принадлежит только «Berger», а «Schmitt» принадлежит только «Chief»?
Показать ещё 5 комментариев
Теги:

3 ответа

2
Лучший ответ

Вы не указали СУБД. Это проверено в SQL Server:

with C as
(
  select *,
         row_number() over(partition by value1 order by ID) as rn1,
         row_number() over(partition by value2 order by ID) as rn2
  from YourTable
)
select A.ID, 
       A.name as nameA, 
       B.name as nameB, 
       A.value1  
from C as A
  inner join C as B
    on A.value1 = B.value2 and
       A.rn1 = B.rn2

Испытуемый образец:

declare @T table
(
  ID int,
  name varchar(10),
  value1 int,
  value2 int
)
insert into @T values
(1,          'Meyer',         20,          null),
(2,          'Schmitt',       20,          null),
(3,          'Berger',        null,        20),
(4,          'Chief',         null,        20)

;with C as
(
  select *,
         row_number() over(partition by value1 order by ID) as rn1,
         row_number() over(partition by value2 order by ID) as rn2
  from @T
)
select A.ID, 
       A.name as nameA, 
       B.name as nameB, 
       A.value1  
from C as A
  inner join C as B
    on A.value1 = B.value2 and
       A.rn1 = B.rn2
  • 0
    Хей! Сперва спасибо Это похоже на решение, но извините, я просто работаю с sqlite! Также возможно там? Я никогда не видел WITH C AS (...) Не могли бы вы объяснить это мне? Также возможно в sqlite?
  • 0
    @airfrank - with c as является распространенным табличным выражением. Не знаю, если это доступно в sqlite. Если нет, вы должны использовать два подзапроса. Вам также нужна функция ранжирования row_number (), и, поскольку я ничего не знаю о sqlite, я не могу сказать вам, является ли это вариантом для вас.
Показать ещё 1 комментарий
2

Согласно этому критерию соединения A.value1 = B.value2 и вашей входной таблице, Мейер связан как с Бергером, так и с Шефом, а Шмитт связан как с Бергером, так и с начальником. Таким образом, подозреваемый больше подходит к критериям/бизнес-правилам того, как они связаны, о которых вы нам не говорите. Похоже, вы просто используете value1 и value2 как некоторые фанковые внешние ключи. Непонятно, почему вы думаете, что Мейер не будет связан с начальником, или почему Шмитт не будет связан с Бергером.

ID         name          value1      value2
1          Meyer         20          _
2          Schmitt       20          _
3          Berger        _           20
4          Chief         _           20

Так что это не проблема с вашим запросом, а проблема с вашей структурой данных, поэтому давайте исправить значение1 и значение2:

ID         name          value1      value2
1          Meyer         10          _
2          Schmitt       20          _
3          Berger        _           10
4          Chief         _           20

Теперь вы получите правильные результаты. Но более традиционный дизайн будет выглядеть так:

PersonId   PersonName    BossPersonId
1          Meyer         3
2          Schmitt       4
3          Berger        _
4          Chief         _

С помощью этого запроса:

Select A.Id, A.PersonName, B.PersonName as BossName
FROM table AS A INNER JOIN table AS B
ON A.BossPersonId= B.PersonId   
  • 0
    Хей! Сперва спасибо Я не забочусь о спаривании! Я просто хочу, чтобы ничего не было в паре дважды. Как объяснено в комментарии выше. Есть идеи?
0

Я решил это прямо сейчас.

ТАБЛИЦА:

ID       name         value1         value2
1        Meyer        20             _
2        Muster       10             _
3        Heinz        20             _
4        Karl         _              20
5        Max          _              20
6        Zack         _              10

Разделите его в временных таблицах и закажите его по значению

ТАБЛИЦА А:

ID       name        value1        value2
1        Muster      10            _
2        Meyer       20            _
3        Heinz       20            _

ТАБЛИЦА B:

ID       name        value1        value2
1        Zack        _             10
2        Karl        _             20
3        Max         _             20

и затем присоединитесь к A.ID = B.ID AND A.value1 = B.value2

Сообщение с рулонами мне очень помогло, с наилучшими пожеланиями

Ещё вопросы

Сообщество Overcoder
Наверх
Меню