Имя: Пароль:
1C
 
Помогите разобраться с 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) Не за что.