|
Помогите разобраться с SQL | ☑ | ||
---|---|---|---|---|
0
1сПупс
27.09.22
✎
15:19
|
Есть таблица Transactions (колонки id, id_products, id_store, date)
есть таблица Products (id, name) есть таблица store(id, name) Как мне в запросе вывести не только айдишники продуктов и магазинов, но их имена? |
|||
1
Kongo2019
27.09.22
✎
15:21
|
(0) SQL JOIN - соединение таблиц базы данных
|
|||
2
1сПупс
27.09.22
✎
15:22
|
Select
Products.name, Store.name, date from Transactions limit 10 |
|||
3
1сПупс
27.09.22
✎
15:24
|
Select
Products.name, Store.name, date from Transactions left join Products on Transactions.id_products = Products.id одну таблицу связал, а как же вторую? (store) |
|||
4
Gary417
27.09.22
✎
15:25
|
еще раз join?
|
|||
5
Gary417
27.09.22
✎
15:27
|
чёт типа так както
.... from Transactions left join Products on Transactions.id_products = Products.id left join Store On Transactions.id_store = Store.id ... |
|||
6
1сПупс
27.09.22
✎
15:31
|
SELECT
id_transaction, stores.name_store as name_store, products.category as category_id_product, products.name as продукт FROM transactions inner join products ON transactions.id_product = products.id_product inner JOIN stores ON transactions.id_store = stores.id_store |
|||
7
1сПупс
27.09.22
✎
15:35
|
так вроде работает, но можно ли обойтись без соединений?
типа SELECT id_transaction, stores.name_store as name_store, products.category as category_id_product, products.name as продукт FROM transactions, products, stores |
|||
8
Йохохо
27.09.22
✎
15:43
|
(7) так даже больше будет, если платят за размер результата самое то
|
|||
9
lite777
27.09.22
✎
15:59
|
(7) Так все комбинации выйдут , см 6 Левое Соединение 2 раза
|
|||
10
mistеr
27.09.22
✎
16:00
|
(7) Это тебе не 1С, детка. Без соединений никак.
Кстати, в Оракле можно обращение через точку организовать. Но этим мало кто пользуется. |
|||
11
Мультук
гуру
27.09.22
✎
16:04
|
(7)
Конечно можно. В старину так и писали (даже в одной из книг Грубера были примеры). Но зачем ? SELECT id_transaction, stores.name_store as name_store, products.category as category_id_product, products.name as продукт FROM transactions, products, stores WHERE transactions.id_product = products.id_product AND transactions.id_store = stores.id_store |
|||
12
H A D G E H O G s
27.09.22
✎
16:06
|
Я думаю, у автора троллит.
|
|||
13
bolder
27.09.22
✎
18:39
|
(7) Можно но не нужно.Затраты на выполнение (11) в 4 раза больше (5), два Hash Match убивают производительность.
|
|||
14
Said_We
27.09.22
✎
18:56
|
(0) Можно и так.
Select (SELECT name from products as t1 where t.id_products = t1.id limit 1) as name_product ,(SELECT name from store as t2 where t.id_store = t2.id limit 1) as name_store from Transactions as t |
|||
15
Said_We
27.09.22
✎
18:58
|
Точнее так
Select (SELECT t1.name from products as t1 where t.id_products = t1.id limit 1) as name_product ,(SELECT t2.name from store as t2 where t.id_store = t2.id limit 1) as name_store from Transactions as t |
|||
16
Said_We
27.09.22
✎
19:16
|
Не нужны тут соединения. Это стандартная задача.
|
|||
17
Злопчинский
27.09.22
✎
23:25
|
(16) а почему соединения не нужны?
на большом объеме данных - какой вариант будет лучше - с соединениями или без? |
|||
18
mistеr
27.09.22
✎
23:30
|
(13) Ты с настоящим SQL только по книжкам знаком? Планы будут одинаковые.
|
|||
19
mistеr
27.09.22
✎
23:32
|
(15) В реальной жизни за такое бьют по рукам.
|
|||
20
DrZombi
гуру
28.09.22
✎
06:51
|
(0) Почитайте про соединения :)
https://www.sqlshack.com/learn-sql-inner-join-vs-left-join/ Статья англо, но Хром вам поможет :) |
|||
21
DrZombi
гуру
28.09.22
✎
06:52
|
(11) Вы ресурсы не экономите... Вижу черту 1С-ника :)
|
|||
22
NorthWind
28.09.22
✎
06:55
|
(11) компактнее и, на мой взгляд, удобнее. У Оракла еще есть оператор (+) для обозначения опциональной таблицы в соединении, если хочешь писать так, т.е. можно ... WHERE LeftTable.ID(+)=RightTable.LeftID. Как по мне - удобно.
|
|||
23
DrZombi
гуру
28.09.22
✎
06:55
|
(7) Если вам скорость не важна, и вы любите простым запросиком вешать SQL, то можно и без соединений :)
|
|||
24
NorthWind
28.09.22
✎
08:23
|
(21) это вполне нормальный запрос. Просто синтаксис SQL немного другой. См. (18).
|
|||
25
Said_We
28.09.22
✎
11:04
|
(19) Прямые запросы в 1С77 такие конструкции использует. По рукам никого не били и не переписали.
|
|||
26
Said_We
28.09.22
✎
11:13
|
(25) Прямые запросы имеется ввиду 1С++ на 77 и класс "Прямой запрос".
|
|||
27
Said_We
28.09.22
✎
11:18
|
В случае с внутренним и левым соединением, присутствием id_products в таблице Transactions и отсутствием ID в таблице Products количество записей будет разное.
С id_store аналогично. И это тоже жизнь - битые ссылки. |
|||
28
Said_We
28.09.22
✎
11:28
|
(17) Вариант в (15) отработает быстро. Там для каждой записи таблицы Transactions отбирается первая попавшиеся запись из таблиц Products и store по соответствующим полям с ID.
|
|||
29
mistеr
28.09.22
✎
11:28
|
(25) Я имею в виду в не-1С разработке.
|
|||
30
Said_We
28.09.22
✎
11:33
|
(29) В стандартной разработке на 1С такие конструкции не поддерживаются.
В не стандартной 1С++ на 1С 77 использовали именно эту конструкцию (ещё лет 15-17 назад). Она корректнее отрабатывает в случае с не корректными данными и по времени достаточно быстро. |
|||
31
Said_We
28.09.22
✎
21:23
|
(0) Так запрос в (15) подойдет?
|
|||
32
bolder
28.09.22
✎
21:28
|
(18) Я не теоретик, как вы.План запросов показывает 4-х кратное снижение производительстности без соединений, как я и писал в (13):
https://ibb.co/WcPKNrv |
|||
33
Said_We
28.09.22
✎
22:07
|
(32) А без джойнов?
|
|||
34
DrZombi
гуру
29.09.22
✎
06:21
|
(24) Посмотрите, тут люди уже доказывают обратное в (32) :)
|
|||
35
katamoto
29.09.22
✎
06:38
|
(32) Не показательно, на самом деле. Это планы только на ваших тестовых данных, в реальности они могу быть совершенно другие, в зависимости от количества строк в таблицу и наличия индексов
|
|||
36
DrZombi
гуру
29.09.22
✎
06:42
|
(35) В общем, для стабильности, ИМХО - если чего, лучше связи прописывать :)
И INNER работает тормознутее, чем тот же LEFT (для справки, если чего) :) |
|||
37
katamoto
29.09.22
✎
07:01
|
(36) Inner join и left join это логические операторы, так что бессмысленно говорить что один из них быстрее другого. Нужно смотреть какие физические методы доступа оптимизатор решит использовать в конкретном случае. А это уже сильно зависит от множества других факторов, по одному тексту запроса сказать нельзя.
|
|||
38
DrZombi
гуру
29.09.22
✎
07:32
|
(37) Ну да, нуда... Вы как начнете использовать Терабайтные базы в SQL запросах, то не забудьте поиграться Join-ами, вас позабавит разница в Left и Inner :)
|
|||
39
mistеr
29.09.22
✎
07:44
|
(32) Если хочешь быть практиком, то:
1) наполни таблицы более-менее реальным количеством данных; в частности, transactions >> products >> store 2) добавь необходимые индексы 3) собери статистику 4) смотри на реальную статистику выполнения, а не только план. |
|||
40
katamoto
29.09.22
✎
07:45
|
(38) Объем базы абсолютно ничего не говорит о квалификации того, кто с ней работает, в общем-то
|
|||
41
mistеr
29.09.22
✎
07:54
|
(36) Интересно, в каких случаях и почему?
|
|||
42
Said_We
29.09.22
✎
10:11
|
(32) А без джоинов как в (15) за сколько отработает?
|
|||
43
Said_We
29.09.22
✎
11:46
|
(32) Пробовать значит не будите.....
|
|||
44
Said_We
29.09.22
✎
15:00
|
(32) хозяин барин....
|
|||
45
Курцвейл
29.09.22
✎
15:40
|
(38) Inner ВСЕГДА быстрее LEFT за редким исключением. Исключение - кривые руки проектировщика решения.
|
|||
46
bolder
29.09.22
✎
16:32
|
(43) Я попытался скопировать ваш код из (15) но запрос не выполняется из-за ошибки идентификатора t.id_products не может получить.
MSSQL 2014.На другом сервере пока не могу попробовать, просто нет времени. |
|||
47
Sserj
29.09.22
✎
16:33
|
(42) Тут вобщем то ни разу не сказали что за движок базы. А судя по (2) это и вовсе не ms-sql а что-то типа sqlite или mysql.
Ну так вот в MS-SQL с вероятностью процентов 95 эти запросы развернутся в left join. Свежие sql-серверы очень умные штуки. |
|||
48
bolder
29.09.22
✎
16:34
|
(47) Результаты в (32) получены на MSSQL 2014
|
|||
49
bolder
29.09.22
✎
16:36
|
(39) Проведу такие эксперименты, но до выходных просто физически нет времени.
|
|||
50
Мультук
гуру
29.09.22
✎
16:39
|
(49)
Если уж сравнивать планы,то LEFT JOIN INNER JOIN Неявный Inner join А сравнивать Left join И неявный inner join -- такое себе счастье |
|||
51
Said_We
29.09.22
✎
16:40
|
(46) В описании в (0) поле называется "id_products" судя по (32) называется "id_prod", а может поле называется "id_product".
|
|||
52
bolder
29.09.22
✎
16:44
|
(51) Не не я десять раз идентификаторы сверил.Проблема именно вовнутреннем условии на внешнее поле.Если у кого-то получилось, был бы рад посмотреть.
|
|||
53
Said_We
29.09.22
✎
16:51
|
(52) Рабочий способ. Поддерживается и Ораклом и MS SQL и MySQL и SQLite и...
https://sql-academy.org/ru/trainer/tasks/1 SELECT t1.id ,(SELECT t.name FROM passenger as t WHERE t1.passenger = t.id ) as name FROM Pass_in_trip as t1 |
|||
54
Said_We
29.09.22
✎
16:55
|
К (53) Limit 1 не указал. На старых версиях MYSQL не отработает. Для MS SQL соответственно TOP 1 и может потребовать ORDER BY t.id.
SELECT t1.id ,(SELECT t.name FROM passenger as t WHERE t1.passenger = t.id limit 1) as name FROM Pass_in_trip as t1 |
|||
55
Said_We
29.09.22
✎
16:57
|
Для MS SQL наверное так будет:
SELECT t1.id ,(SELECT TOP 1 t.name FROM passenger as t WHERE t1.passenger = t.id order by t.id) as name FROM Pass_in_trip as t1 |
|||
56
bolder
29.09.22
✎
17:05
|
(50) Вобщем, как ожидалось.Лучше всех - в 4 раза LEFT JOIN.
https://ibb.co/QcqWMKR |
|||
57
Said_We
29.09.22
✎
17:12
|
(56) Ждем четвертый вариант.
|
|||
58
bolder
29.09.22
✎
17:21
|
(55) То что надо! Стоимость (55) аналогична LEFT JOIN b в четыре раза лучше без соединений и INNER JOIN.
https://ibb.co/vvvb7m3 |
|||
59
Said_We
29.09.22
✎
17:36
|
(58) Что и ожидалось и о чем писалось выше. Спасибо.
|
|||
60
1сПупс
03.10.22
✎
10:15
|
решаю задачу https://sql-academy.org/ru/trainer/tasks/18
хочу написать так: SELECT member_name FROM FamilyMembers WHERE birthday = MIN(birthday) но пишет ошибку. Разве можно только так?: SELECT member_name FROM FamilyMembers WHERE birthday = (SELECT MIN(birthday) FROM FamilyMembers) |
|||
61
Тихий омут
03.10.22
✎
10:30
|
(60) select top (1) * from v8users order by v8users.Changed asc
|
|||
62
Said_We
03.10.22
✎
11:29
|
(60) Можно так:
SELECT t.member_name as member_name from (SELECT member_name as member_name ,birthday as birthday ,min(birthday) over () as old_birthday FROM FamilyMembers) as t WHERE t.birthday = t.old_birthday |
|||
63
Said_We
03.10.22
✎
12:33
|
(60) А чем показался ваш вариант плох?
Который вот этот: SELECT member_name FROM FamilyMembers WHERE birthday in (SELECT MIN(birthday) FROM FamilyMembers) |
|||
64
1сПупс
03.10.22
✎
13:58
|
(61) так можно:
SELECT member_name FROM FamilyMembers ORDER BY birthday ASC LIMIT 1 спасибо! |
|||
65
Said_We
03.10.22
✎
14:02
|
(64) Нельзя. Могут быть одинакового возраста и самые старшие.
|
|||
66
1сПупс
03.10.22
✎
14:10
|
(65) согласен, если база на 234234 строк могут быть те, кто родился в один день.
|
|||
67
1сПупс
03.10.22
✎
14:11
|
(66) + просто привел вариант Тихий омут в божеский вид mssql
|
|||
68
Said_We
03.10.22
✎
14:18
|
(67) SQL Academy - это MySQL.
Защиты от дурака на этом сайте нет. Можно нарисовать любой запрос, если он для единственной базы вернёт правильный результат, то и запрос будет считаться правильным. А очень часто это не так. |
|||
69
1сПупс
03.10.22
✎
18:12
|
(65) в задаче https://sql-academy.org/ru/trainer/tasks/23 похожие условия, нужно выбрать самые дорогие деликатесы.
написал SELECT good_name, unit_price FROM Payments JOIN Goods ON Payments.good = Goods.good_id JOIN GoodTypes ON Goods.type = GoodTypes.good_type_id WHERE good_type_name = 'delicacies' ORDER BY unit_price DESC LIMIT 1 но понимаю что там может быть несколько деликатесов с одинаковой ценой. |
|||
70
Said_We
03.10.22
✎
18:37
|
(69) А если так?
SELECT (SELECT t2.good_name FROM Goods as t2 WHERE t1.good = t2.good_id ORDER BY t2.good_id LIMIT 1 ) as good_name ,t1.unit_price as unit_price FROM (SELECT good as good ,unit_price as unit_price ,max(unit_price) over() as maxPrice FROM Payments where good in (SELECT good_id FROM Goods WHERE type in (SELECT good_type_id FROM GoodTypes WHERE good_type_name = "delicacies" ) ) ) as t1 WHERE t1.unit_price = t1.maxPrice |
|||
71
Said_We
03.10.22
✎
18:44
|
В первый select надо добавить ещё DISTINCT как минимум.
А то если один и тот же деликатес продавали по максимальной цене несколько раз, то и строчек будет столько же... :-) |
|||
72
Said_We
03.10.22
✎
18:47
|
(69) Зачем каждый раз используешь join?
join - это убийца производительности запросов. Его необходимо использовать и без него никак, где есть реальное соединение таблиц. А где нет соединения таблиц, то лучше не использовать. |
|||
73
1сПупс
03.10.22
✎
19:04
|
(70)решил сделать так, может и не правильно:
SELECT good_name, unit_price FROM Payments JOIN Goods ON Payments.good = Goods.good_id JOIN GoodTypes ON Goods.type = GoodTypes.good_type_id WHERE good_type_name = 'delicacies' AND unit_price in ( SELECT MAX(unit_price) FROM Payments JOIN Goods ON Payments.good = Goods.good_id JOIN GoodTypes ON Goods.type = GoodTypes.good_type_id GROUP BY good_type_name HAVING good_type_name = 'delicacies' |
|||
74
Said_We
03.10.22
✎
19:07
|
(73) Хозяин барин. Прямо тянет на джоины, ну что тут поделаешь....
Выполни кусок запроса и посмотри как работает "max(unit_price) over() as maxPrice" SELECT good as good ,unit_price as unit_price ,max(unit_price) over() as maxPrice FROM Payments where good in (SELECT good_id FROM Goods WHERE type in (SELECT good_type_id FROM GoodTypes WHERE good_type_name = "delicacies" ) ) |
|||
75
1сПупс
04.10.22
✎
16:41
|
(74) спасибо что помогаете, но пока тяжело без джунов, возможно к этому приду.
Решаю задачу https://sql-academy.org/ru/trainer/tasks/37 SELECT FLOOR((MIN(DATEDIFF(CURRENT_TIMESTAMP(), birthday)/365))) AS year FROM Student ответ то верный, но может есть решение проще, без костылей? Для справки использую https://habr.com/ru/post/564390/#что-такое-sql |
|||
76
mistеr
04.10.22
✎
16:56
|
(72) Джойны это основа основ реляционных БД.
А убийцы производительности это кривые руки и каша в голове. |
|||
77
mistеr
04.10.22
✎
17:04
|
(75) Нормальное решение. Упростить можно только DATEDIFF(CURRENT_TIMESTAMP(), MAX(birthday))
|
|||
78
Said_We
04.10.22
✎
19:12
|
(76) Не внимательно читаете. Третью строчку не читали или решили остановится на второй? :-)
|
|||
79
1сПупс
04.10.22
✎
20:30
|
делаю задачу https://sql-academy.org/ru/trainer/tasks/49
сделал запрос: ученики класса 10а: SELECT COUNT(*) FROM Student JOIN Student_in_class ON Student.id = Student_in_class.student JOIN Class ON Class.id = Student_in_class.class WHERE name = '10 A' все ученики: SELECT COUNT(*) FROM Student JOIN Student_in_class ON Student.id = Student_in_class.student JOIN Class ON Class.id = Student_in_class.class Хотелось бы результат запроса 1 передать в переменную 1, а потом результат запроса 2 передать в переменную 2, а потом одно разделить на другое. Как это можно сделать? Или задача решается по другому? |
|||
80
mistеr
04.10.22
✎
21:38
|
(79) Используй левое соединение Student к Student_in_class с условием класс только 10А.
По этой выборке ты сможешь сразу подсчитать и общее количество и в этом классе, и разделить. |
|||
81
Мультук
гуру
04.10.22
✎
22:01
|
(79)
SELECT count (case when class.name = '10 A' then Student_in_class.student else null end) / count (Student_in_class.student) * 100 as percent FROM Student_in_class left JOIN Class ON Class.id = Student_in_class.class P.S. Left - потому что в этом странном заведении в таблице Student_in_class есть записи с "class", которых нет в таблице class |
|||
82
mistеr
04.10.22
✎
22:09
|
(81) Теоретически студент может участвовать в нескольких классах.
|
|||
83
Мультук
гуру
04.10.22
✎
22:16
|
(82)
Я о ситуации, когда запрос возвращает строки. SELECT Student_in_class.id, Student_in_class.class, class.name FROM Student_in_class left JOIN Class ON Class.id = Student_in_class.class where Class.id is null |
|||
84
mistеr
04.10.22
✎
22:19
|
(83) Я понял. А я о том, что соединение нужно в другую сторону.
|
|||
85
1сПупс
06.10.22
✎
13:47
|
Делаю задачу https://sql-academy.org/ru/trainer/tasks/60
решил, но долго думал можно ли тут использовать группировку вроде этого: SELECT DISTINCT teacher, FROM Schedule JOIN Class ON Schedule.class = Class.id WHERE name LIKE '11%' GROUP BY teacher, name HAVING COUNT(*)>1 ORDER BY name, teacher вот решение без группировки: SELECT DISTINCT teacher FROM Schedule JOIN Class ON Schedule.class = Class.id WHERE teacher IN ( SELECT teacher FROM Schedule JOIN Class ON Schedule.class = Class.id WHERE name = '11 A' ) AND teacher IN ( SELECT teacher FROM Schedule JOIN Class ON Schedule.class = Class.id WHERE name = '11 B') |
|||
86
Said_We
06.10.22
✎
14:01
|
(85) С формулировкой там всё нормально?
"Выведите идентификаторы преподавателей, которые хотя бы один раз за всё время преподавали в КАЖДОМ из одиннадцатых классов.". Не увидел поиска полного количества 11-х классов, которое потом сравнивается с количеством классов 11-х, по каждому учителю в которых он преподавал. |
|||
87
Said_We
06.10.22
✎
14:41
|
(85) В решении в (85) прописаны жестко 11 А и 11 Б. А если вдруг будет 11 Г, то запрос перестанет работать?
|
|||
88
Мультук
гуру
06.10.22
✎
14:50
|
(85)
1) Зачем тут ORDER by -- что он делает полезного 2) HAVING COUNT(*) = Запрос{Количество 11 классов} |
|||
89
Мультук
гуру
06.10.22
✎
14:59
|
(85)
И еще подсказка having count(*) Вместо * можно написать имя поля или distinct ИмяПоля |
|||
90
Said_We
06.10.22
✎
15:15
|
(85)
Можно и так: WITH Klass_11 as (SELECT id as id FROM class WHERE name LIKE "11%") ,kol_11 as (SELECT COUNT(id) as kol FROM Klass_11) SELECT t.teacher FROM (SELECT t.teacher ,COUNT(t.class) as kol FROM (SELECT DISTINCT teacher ,class from Schedule WHERE class in (SELECT id from Klass_11) ) as t GROUP BY t.teacher ) as t WHERE t.kol in (SELECT t1.kol FROM kol_11 as t1) |
|||
91
Мультук
гуру
06.10.22
✎
15:34
|
(90)
select schedule.teacher from schedule join class on schedule.class = class.id where class.name like '11%' group by schedule.teacher having count(DISTINCT schedule.class) = (select count(id) from class where name like '11%') |
|||
92
Said_We
06.10.22
✎
16:03
|
(91) join, то тут зачем?
В schedule уже есть класс. На него только условие необходимо наложить. WHERE class in (SELECT id as id FROM class WHERE name LIKE "11%") Таблицы тут связывать не к чему на мой взгляд. Тем более вместо условия после связи <where class.name like '11%'>, если уж решили в обязательном порядке использовать джоин, то логичнее вторую таблицу предварительно обрезать как раз этим условием. т.е. до джоина. |
|||
93
Мультук
гуру
06.10.22
✎
16:14
|
(92)
1) Т.е. join это всегда плохо, а in - всегда хорошо ? Много лет назад меня учили ровно до-наборот Правда это был не MS-SQL, а Interbase/Firebird 2) У меня сейчас нет возможности смотреть насколько сильно повлияет на план запроса перетаскивание условия select schedule.teacher from schedule join class on schedule.class = class.id and class.name like '11%' |
|||
94
Said_We
06.10.22
✎
16:24
|
(93) Можно и как ниже. Но тут есть копи паст в виде <FROM class WHERE name LIKE "11%">
SELECT t.teacher FROM (SELECT teacher ,DENSE_RANK() over (partition by teacher ORDER by teacher, class) as r from Schedule WHERE class in (SELECT id as id FROM class WHERE name LIKE "11%") ) as t GROUP BY t.teacher HAVING max(t.r) = (SELECT COUNT(id) as id FROM class WHERE name LIKE "11%") (93) А что тут гадать про данный случай. В результате всего несколько 11 классов. Или их количество всегда одна строчка. Это условие на очень ограниченное количество значений. IN тут и более читабелен и по скорости уж точно медленнее не будет. |
|||
95
Said_We
06.10.22
✎
17:13
|
(93) Такая связь:
select schedule.teacher from schedule join class on schedule.class = class.id and class.name like '11%' Точно хуже такой: select schedule.teacher from schedule join (select id from class where name like '11%') as t2 on schedule.class = t2.id Зачем связывать со всеми классами и потом накладывать условия только на классы, когда можно сразу связывать с уже ограниченным количеством классов. Таблица изначально уже меньше. Решение в (90) более прозрачное и легко читаемое. Решение в (94) по сути тоже самое, но менее понятным языком. |
|||
96
Said_We
09.10.22
✎
23:57
|
(0) Все задачи уже сделал?
|
|||
97
Said_We
10.10.22
✎
16:44
|
Скорее всего уже все сделал.
Хоть впечатлениями бы поделился. |
|||
98
1сПупс
10.10.22
✎
19:09
|
(96) решаю задачу https://sql-academy.org/ru/trainer/tasks/68
Впечатления такие, что будто заново изобретаю велосипед. Получаю комнаты и даты выезда очень просто, только не могу понять как сюда припаять user_id: SELECT room_id, MAX(end_date) as end_date FROM Reservations GROUP BY room_id Сделал так, но по-моему это слишком заумно, поправьте если не прав. SELECT V.room_id, name, V.end_date FROM ( SELECT room_id, MAX(end_date) as end_date FROM Reservations GROUP BY room_id) as V JOIN Reservations ON V.end_date = Reservations.end_date AND V.room_id = Reservations.room_id JOIN Users ON Reservations.user_id = Users.id |
|||
99
mistеr
10.10.22
✎
20:40
|
(98) Все верно, только я бы ориентировался на на end_date, а на start_date при поиске последней брони.
|
|||
100
Said_We
10.10.22
✎
21:44
|
(98) А если так?
SELECT t.room_id ,(SELECT name FROM Users as t1 WHERE t.user_id = t1.id) as name ,end_date from (SELECT row_number() over(partition by room_id order by end_date DESC) as npp ,room_id ,user_id ,end_date FROM Reservations ) as t WHERE t.npp = 1 |
|||
101
Said_We
10.10.22
✎
22:01
|
Если совсем правильно, то после:
WHERE t.user_id = t1.id должен быть ещё и LIMIT: LIMIT 1 ) as name Но версия MYSQL, которая проверяет "хавает" и так, так как user_id вторичный ключ и id первичный ключ. Более ранние версии могут в ошибку уходить. |
|||
102
Said_We
10.10.22
✎
22:05
|
(99) Зачем ориентироваться на дату заезда? Какая разница когда постоялец въехал, важно когда выехал и то, что он последний.
|
|||
103
Said_We
10.10.22
✎
22:07
|
(98) "Впечатления такие, что будто заново изобретаю велосипед." - это нормальные впечатления.
Голова должна просто перестроится и усё. Это практика и время. У всех по разному с точки зрения времени. Но так же как с велосипедом - один раз научишься и более не разучишься. |
|||
104
mistеr
11.10.22
✎
09:47
|
(102) При нормальном проектировании там будет констрейнт уникальности (user_id, start_date), что позволяет не думать о дублях, да и слегка побыстрее будет, скорее всего. Но это уже за рамками задачи.
|
|||
105
Said_We
11.10.22
✎
10:14
|
(104) Ничего не понял из сказанного.
Номера могут быть с подселением. Поэтому не важно последний он в номер заехал или первый. Важно кто последний выехал, так как именно это спрашивается из задания. Более того на сейчас могут быть заехавшие и ещё не выехавшие и проживающие. По заданию они нас не интересуют. |
|||
106
mistеr
11.10.22
✎
10:39
|
(105) "person who last rented it" это тот кто последний въехал/забронировал.
Причем тут подселение, не понял. Даже если возможно, по-моему, это ничего не меняет. |
|||
107
1сПупс
11.10.22
✎
10:43
|
(105) все прорешал, всем спасибо за помощь, оссобенно Said_We
Впечатление хорошее, полезный ресурс. Для себя открыл несколько ресурсов для справки: https://oracleplsql.ru/mysql-manual.html http://www.sql-tutorial.ru/ru/content.html https://habr.com/ru/post/564390/ |
|||
108
Said_We
11.10.22
✎
10:44
|
(106) Я не читал английский вариант задания. По русски он выглядит так:
"#68 Для каждой комнаты, которую снимали как минимум 1 раз, найдите имя человека, снимавшего ее последний раз, и дату, когда он выехал". |
|||
109
Said_We
11.10.22
✎
10:48
|
(106) "Причем тут подселение, не понял. Даже если возможно, по-моему, это ничего не меняет."
Ну как же не меняет? Представь вариант. Комната ФИО ДатаН ДатаК 1 Иванов И.И. 01.01.2022 31.01.2022 1 Петров С.О. 06.01.2022 15.01.2022 |
|||
110
mistеr
11.10.22
✎
11:35
|
(109) Последним снял Петров, выехал 15-го.
|
|||
111
Said_We
11.10.22
✎
12:12
|
(110) Последним снимал и выехал Иванов, так как он ещё две недели жил в номере, после того как Петров из номера выехал.
|
|||
112
Said_We
11.10.22
✎
12:14
|
(110) Автор закончил курс SQL Academy в части select, о чем написал в (107). Ветку можно закрывать.
(107) Не за что. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |