SQL-запрос для отображения строк, которые имеют только одно значение в таблице - PullRequest
2 голосов
/ 30 сентября 2011

У меня проблема с написанием SQL в SQL Server. Вот случай, у меня есть три таблицы с именами User, Client и UserClient. Ниже приведен пример содержания таблицы

КЛИЕНТ

idClient     | client
____________________________
1            | Client A
2            | Client B
3            | Client C

USER

idUser       | User
____________________________
1            | User A
2            | User B
3            | User C

USERCLIENT

idUserClient | idUser     | idClient
____________________________________
1            | 1          | 1
2            | 1          | 2
3            | 2          | 1
4            | 2          | 3
5            | 3          | 1

Мне нужен запрос, чтобы показать пользователю с idClient = 1 И иметь только одного клиента из таблицы USERCLIENT. Как показано в приведенном выше примере, результат запроса должен быть

idUserClient | idUser     | idClient
_________________________________________
5            | 3          | 1

Ответы [ 6 ]

2 голосов
/ 30 сентября 2011

(1) Если вам нужно только idUser:

SELECT idUser 
FROM USERCLIENT 
GROUP BY idUser 
HAVING COUNT(*)=1

(2) Если вам нужны все поля из таблицы USERCLIENT:

SELECT  *
FROM    USERCLIENT a
INNER JOIN
(
    SELECT idUser 
    FROM USERCLIENT 
    GROUP BY idUser 
    HAVING COUNT(*)=1
) b ON a.idUser=b.idUser
1 голос
/ 30 сентября 2011

Это сработало для меня ...

with cte AS
(
    SELECT 1 AS idUserClient, 1 AS idUser, 1 AS idClient 
    UNION
    SELECT 2 AS idUserClient, 1 AS idUser, 2 AS idClient 
    UNION
    SELECT 3 AS idUserClient, 2 AS idUser, 1 AS idClient 
    UNION
    SELECT 4 AS idUserClient, 2 AS idUser, 3 AS idClient 
    UNION
    SELECT 5 AS idUserClient, 3 AS idUser, 1 AS idClient 
)
SELECT * FROM cte c1
WHERE 
    idUserClient IN 
    (
        SELECT MIN(c2.idUserClient) FROM cte c2 GROUP BY c2.idUser HAVING COUNT(c2.idUser) = 1
    )
1 голос
/ 30 сентября 2011

БИНГО!

SELECT * FROM USERCLIENT WHERE iduser IN 
 (SELECT iduser FROM USERCLIENT GROUP BY iduser HAVING COUNT(iduser)=1)
0 голосов
/ 30 сентября 2011

Это покажет пользователей, которые связаны с клиентом idClient = 1 и только с этим клиентом:

SELECT
  MAX(idUserClient) AS idUserClient,
  idUser,
  MAX(idClient) AS idClient
FROM USERCLIENT
GROUP BY idUser
HAVING COUNT(*) = 1
   AND COUNT(CASE idClient WHEN 1 THEN 1 END) = 1

Предложение HAVING проверяет, что группа строк для пользователя содержит ровно одну строку и среди«их» есть ровно одна строка, где idClient = 1.

В качестве альтернативы, SQL Server 2008 позволит вам сделать что-то вроде этого:

WITH ranked AS (
  SELECT
    *,
    rnk = ROW_NUMBER() OVER (
      PARTITION BY idUser
      ORDER BY CASE idClient WHEN 1 THEN 1 ELSE 0 END, idClient
    )
  FROM USERCLIENT
)
SELECT
  idUserClient,
  idUser,
  idClient
FROM ranked
WHERE rnk = 1
  AND idClient = 1

CTE ранжирует строки в USERCLIENTтаким образом, что если пользователь связан с idClient = 1 и не имеет другого клиента, соответствующая строка оценивается как 1, в противном случае строка с idClient = 1 (если такой присутствует) получает другой ранг.Поэтому при выборе из CTE вам просто нужно отфильтровать по rnk = 1 AND idClient = 1.

0 голосов
/ 30 сентября 2011

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

select * from userclient where idUser = 3

или

select * form userClient where idUser = 3 and idClient = 1

Я не уверен, что вы действительно хотите, но эти два случая приводят к результату.

Что вы должны запросить?

0 голосов
/ 30 сентября 2011

Предполагая, что (idUser, idClient) является уникальным индексом:

SELECT USERCLIENT.idUser
FROM USER
   INNER JOIN USERCLIENT
       ON USER.idUser = USERCLIENT.idUser
WHERE USERCLIENT.idClient = 1
GROUP BY USERCLIENT.idUser
HAVING COUNT(*) = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...