Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Inner join да не простой  [new]
N_Reeke
Member

Откуда:
Сообщений: 15
Не могу понять, где я ошибся. Помогите, пожалуйста.
Есть задание "Вывести компании где женатых сотрудников с зарплатой больше 1500 меньше, чем не женатых с зарплатой больше 1500".
Дано две таблицы:

Employee
ID Name Salary Age Status
1 Alex 1000 1,5 Married
2 Nik 2500 5 Single
3 Jed 1500 3 Single
4 Tod 700 1 Married
5 Karl 200 0,5 Married
6 Emily 4000 10 Married
7 Den 5000 7 Single
8 Mark 800 2 Single

Company
Id Company_Name Employee_id
1 Google 7
2 Apple 2
2 Apple 4
2 Apple 3
1 Google 5
3 Samsung 6
1 Google 1
3 Samsung 8

Мой код:

use [Тест]
go
SELECT c.Company_Name
from employee e
inner join company c
on e.ID = c.employee_id
Where ((select count(e.Name) from employee e
where e.status = 'Married'
And e.salary > 1500) < (select Count(e.Name) from employee e
where e.status = 'Single'
And e.salary > 1000))
Group by c.Company_name;

В результате запроса - все три компании, что не есть корректно.

Заранее благодарю!
9 фев 19, 15:41    [21805254]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
Tactical Nuclear Penguin
Member

Откуда: холодно тут
Сообщений: 2702
And e.salary > 1000))


что за 1000 для начала?
9 фев 19, 16:18    [21805275]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
iap
Member

Откуда: Москва
Сообщений: 46862
SELECT c.Company_Name
FROM Company c
JOIN Employee e ON c.Employee_id=e.ID
GROUP BY c.Company_Name
HAVING SUM(CASE WHEN e.Status='Married' AND e.Salary>1500 THEN 1 ELSE 0 END)
      <SUM(CASE WHEN e.Status='Single'  AND e.Salary>1500 THEN 1 ELSE 0 END);
9 фев 19, 16:25    [21805278]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
invm
Member

Откуда: Москва
Сообщений: 8802
select
 c.Company_Name
from
 employee e
 inner join company c on e.ID = c.employee_id
group by
 c.Company_name
having
 count(case when e.status = 'Married' and e.salary > 1500 then 1 end) < count(case when e.status = 'Single' and e.salary < 1500 then 1 end);
9 фев 19, 16:27    [21805279]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
iap
Member

Откуда: Москва
Сообщений: 46862
invm
select
 c.Company_Name
from
 employee e
 inner join company c on e.ID = c.employee_id
group by
 c.Company_name
having
 count(case when e.status = 'Married' and e.salary > 1500 then 1 end) < count(case when e.status = 'Single' and e.salary < 1500 then 1 end);
Оба раза БОЛЬШЕ 1500 в условии задачи!
9 фев 19, 16:35    [21805288]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
invm
Member

Откуда: Москва
Сообщений: 8802
iap
Оба раза БОЛЬШЕ 1500 в условии задачи!
Ок.
select
 c.Company_Name
from
 employee e
 inner join company c on e.ID = c.employee_id
where
 e.salary > 1500
group by
 c.Company_name
having
 count(case when e.status = 'Married' then 1 end) < count(case when e.status = 'Single' then 1 end);
9 фев 19, 17:28    [21805323]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
N_Reeke
Member

Откуда:
Сообщений: 15
Спасибо всем!
Да, извините. ошибся в условии *чем не женатых с зарплатой больше 1000*.
9 фев 19, 17:43    [21805334]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
invm,

Я Вас таки совсем немного чуть-чуть поправлю. Для красоты исключительно.
select
 c.Company_Name
from
 employee e
 inner join company c on e.ID = c.employee_id
where
 e.salary > 1500 and c.Company_Name is not null
group by
 c.Company_name
having
 count(case when e.status = 'Married' then convert(int,1) else convert(int,0) end) < count(case when e.status = 'Single' then convert(int,1) else convert(int,0) end);
// int поскольку на данном этапе развития планеты Земля количество программистов в одной компании не превышает даже миллиона
// в дальнейшем (через несколько тысячелетий) рекомедовано взамен использовать bigint
9 фев 19, 17:46    [21805335]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Andy_OLAP,

И даже можно записать немного не так. А еще кошернее.
select
 c.Company_Name // название компании интересует непустое
from
 employee e
 inner join company c on e.ID = c.employee_id
where
 e.salary > 1500 and c.Company_Name is not null
and e.sex like N'M' // отбираем мужчин-сотрудников, потому что женщины не могут
// быть женатыми, а могут быть замужними
group by
 c.Company_name
having
 count(case when e.status like N'Married%' -- сюда подходят все женатые
then convert(int,1) else convert(int,0) end
) < count(case when e.status not like N'Married%' -- здесь неженатых исключаем, остаются неженатые и вдовцы
then convert(int,1) else convert(int,0) end);
// int поскольку на данном этапе развития планеты Земля
// количество сотрудников в одной компании не превышает даже миллиона
// в дальнейшем (через несколько тысячелетий) рекомедовано
// взамен использовать bigint
9 фев 19, 17:49    [21805336]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
aleks222
Member

Откуда:
Сообщений: 747
Andy_OLAP
И даже можно записать немного не так. А еще кошернее.
select
 c.Company_Name // название компании интересует непустое
from
 employee e
 inner join company c on e.ID = c.employee_id
where
 e.salary > 1500 and c.Company_Name is not null
and e.sex like N'M' // отбираем мужчин-сотрудников, потому что женщины не могут
// быть женатыми, а могут быть замужними
group by
 c.Company_name
having
 count(case when e.status like N'Married%' -- сюда подходят все женатые
then convert(int,1) else convert(int,0) end
) < count(case when e.status not like N'Married%' -- здесь неженатых исключаем, остаются неженатые и вдовцы
then convert(int,1) else convert(int,0) end);
// int поскольку на данном этапе развития планеты Земля
// количество сотрудников в одной компании не превышает даже миллиона
// в дальнейшем (через несколько тысячелетий) рекомедовано
// взамен использовать bigint


Не, джигиты, "вы, как ни садитесь, а в программисты не годитесь".
Зачем вы суете join под группировку?
Ведь ни разу не надо.
Сервер надо любить.

ЗЫ. count(1) = count(0)
10 фев 19, 12:16    [21805596]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
invm
Member

Откуда: Москва
Сообщений: 8802
aleks222
Не, джигиты, "вы, как ни садитесь, а в программисты не годитесь".
Зачем вы суете join под группировку?
Ведь ни разу не надо.
Сервер надо любить.
Так до сих пор и не осознал, что сервер лучше тебя разбирается что сувать под группировку, а что нет?
Снова решил поумничать, даже не посмотрев на структуру исходных данных?
Может тебе уже пора поразмышлять над смыслом пословицы о соринке в чужом глазу?
10 фев 19, 13:24    [21805631]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
iap
Member

Откуда: Москва
Сообщений: 46862
N_Reeke
Спасибо всем!
Да, извините. ошибся в условии *чем не женатых с зарплатой больше 1000*.
Тогда лучше
WHERE e.Status='Married' AND e.Salary>1500 OR e.Status='Single' AND e.Salary>1000
чтобы в WHERE сразу отбросить заведомо неподходящие записи с разными зарплатами.
А в HAVING проверять только Status. Как у invm.
10 фев 19, 15:25    [21805683]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
aleks222
Member

Откуда:
Сообщений: 747
invm
aleks222
Не, джигиты, "вы, как ни садитесь, а в программисты не годитесь".
Зачем вы суете join под группировку?
Ведь ни разу не надо.
Сервер надо любить.
Так до сих пор и не осознал, что сервер лучше тебя разбирается что сувать под группировку, а что нет?
Снова решил поумничать, даже не посмотрев на структуру исходных данных?
Может тебе уже пора поразмышлять над смыслом пословицы о соринке в чужом глазу?

Наивный.
10 фев 19, 16:14    [21805710]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
invm
Member

Откуда: Москва
Сообщений: 8802
aleks222
Наивный.
Это да Картинка с другого сайта.
Невозможно представить ситуацию, когда наш "гура" и "носитель абсолютной истины" признает свою неправоту Картинка с другого сайта.

Еще раз убеждаюсь - тебе просто нравится выставляться идиотом...
10 фев 19, 16:48    [21805725]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
aleks222
Member

Откуда:
Сообщений: 747
invm
aleks222
Наивный.
Это да Картинка с другого сайта.
Невозможно представить ситуацию, когда наш "гура" и "носитель абсолютной истины" признает свою неправоту Картинка с другого сайта.

Еще раз убеждаюсь - тебе просто нравится выставляться идиотом...


1. Любому понятно, что сервер не может сделать никаких предположений относительно company и, в любом случае, сначала с делает соединение, а только потом группировку.
2. Факт того, что соединение под группировкой делается всегда упомянуто и в документации Микрософт.
3. Соединение двух + группировка это больше вычислений и чтений, чем просто группировка одной таблицы.
4. Поэтому, как бы гуру не надувал щеки, на фоне законов природы он такой же нуль, как и любой зауряд-прапорщик.
10 фев 19, 17:24    [21805745]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
invm
Member

Откуда: Москва
Сообщений: 8802
aleks222
1. Любому понятно, что сервер не может сделать никаких предположений относительно company и, в любом случае, сначала с делает соединение, а только потом группировку.
2. Факт того, что соединение под группировкой делается всегда упомянуто и в документации Микрософт.
3. Соединение двух + группировка это больше вычислений и чтений, чем просто группировка одной таблицы.
С нетерпением ждем демонстрации эффективного решения исходной задачи с группировкой одной таблицы или вообще без группировок.

А это тебе для осознания того, как может раскрываться "джойн под группировкой":
use tempdb;
go

create table dbo.t1 (id int primary key, name varchar(100));
create table dbo.t2 (id int primary key, t1_id int, v int);

update statistics dbo.t1 with rowcount = 100;
update statistics dbo.t2 with rowcount = 100000;
go

set statistics xml on;
select b.name, sum(a.v) from dbo.t2 a join dbo.t1 b on b.id = a.t1_id group by b.name;
select b.name, sum(a.v) from dbo.t2 a join dbo.t1 b on b.id = a.t1_id group by b.id, b.name;
set statistics xml off;

alter table dbo.t1 add unique (name);

set statistics xml on;
select b.name, sum(a.v) from dbo.t2 a join dbo.t1 b on b.id = a.t1_id group by b.name;
set statistics xml off;
go

drop table dbo.t1, dbo.t2;
go
Хотя, что-то мне подсказывает, - осознавалка у тебя нерабочая...
aleks222
4. Поэтому, как бы гуру не надувал щеки, на фоне законов природы он такой же нуль, как и любой зауряд-прапорщик.
Опять в зеркале на себя любуешься? Картинка с другого сайта.
10 фев 19, 18:21    [21805769]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
aleks222
Member

Откуда:
Сообщений: 747
invm
aleks222
1. Любому понятно, что сервер не может сделать никаких предположений относительно company и, в любом случае, сначала с делает соединение, а только потом группировку.
2. Факт того, что соединение под группировкой делается всегда упомянуто и в документации Микрософт.
3. Соединение двух + группировка это больше вычислений и чтений, чем просто группировка одной таблицы.
С нетерпением ждем демонстрации эффективного решения исходной задачи с группировкой одной таблицы или вообще без группировок.

А это тебе для осознания того, как может раскрываться "джойн под группировкой":
use tempdb;
go

create table dbo.t1 (id int primary key, name varchar(100));
create table dbo.t2 (id int primary key, t1_id int, v int);

update statistics dbo.t1 with rowcount = 100;
update statistics dbo.t2 with rowcount = 100000;
go

set statistics xml on;
select b.name, sum(a.v) from dbo.t2 a join dbo.t1 b on b.id = a.t1_id group by b.name;
select b.name, sum(a.v) from dbo.t2 a join dbo.t1 b on b.id = a.t1_id group by b.id, b.name;
set statistics xml off;

alter table dbo.t1 add unique (name);

set statistics xml on;
select b.name, sum(a.v) from dbo.t2 a join dbo.t1 b on b.id = a.t1_id group by b.name;
set statistics xml off;
go

drop table dbo.t1, dbo.t2;
go
Хотя, что-то мне подсказывает, - осознавалка у тебя нерабочая...
aleks222
4. Поэтому, как бы гуру не надувал щеки, на фоне законов природы он такой же нуль, как и любой зауряд-прапорщик.
Опять в зеркале на себя любуешься? Картинка с другого сайта.


Опять код не несущий смысловой нагрузки?
Вольно вам веровать, что можно выполнить джойн не выполняя джойн.
Аминь.
11 фев 19, 05:48    [21806019]     Ответить | Цитировать Сообщить модератору
 Re: Inner join да не простой  [new]
invm
Member

Откуда: Москва
Сообщений: 8802
aleks222
Опять код не несущий смысловой нагрузки?
Вольно вам веровать, что можно выполнить джойн не выполняя джойн.
Если нечего ответить по существу, то лучше промолчать.

ЗЫ: Решения задачи ТС без "джойна под группировкой" мы так и не дождемся?
11 фев 19, 10:26    [21806126]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить