• Как составить SQL запрос на выборку из двух таблиц по условию?

    Артём Каретников, все как раз наоборот count(1) не делает лишних заходов в таблицу в отличие от count(*). А top 1 вообще не решает задачу, т.к. может быть несколько пользователей с одинаковым количеством, а top 1 вернёт только первого. Насчёт индексов вообще спорно. В данном случае внутренний и внешний дата сеты могут быть соединены hash join, а это быстрее чем искать по индексу, т.к. поиск по индексу имеет сложность O(log(n)), а поиск по хеш-таблице O(1). Т.е.поиск по хешу не зависит от объема выборки, а поиск по индексу сильно зависит. Кроме этого поиск по индексу требует больше обращений к диску, если индекс не закеширован в памяти, а дисковые операции очень дорогие.
    Вот так как-то. Но если не верите проведите эксперимент, сделайте оба варианта запроса и сравните их планы.
  • Как получить список чисел отсутвующих в базе PostgreSQL?

    Melkij, tempdb в MSSQL, но смысл тот же, либо запрос в оперативке обрабатывается, либо дисковые операции.

    SSD vs RAM, тут от конкретных продуктов зависит, но да тут 1-2 порядка разница в пользу RAM, но уже не 5 порядков как с HDD
  • Как получить список чисел отсутвующих в базе PostgreSQL?

    Melkij, это может быть следствием того, что база тестовая и есть много свободной оперативки для построения хэш таблицы.
    Есть ли индекс по полю id и если есть то какого типа (уникальный, кластерный)?
  • Как получить список чисел отсутвующих в базе PostgreSQL?

    longclaps, согласен, есть нюансы, все зависит от количества записей, которые возвращает вложенный запрос и от типа данных поля по которому проверяем вхождение и от параметров сервера(количество оперативки, типы дисков) и от нагрузки на сервер со стороны других коннектов:

    Вариант с not in:
    1. получаем датасет по вложенному запросу и размещаем его например в tempdb
    (тут имеем накладные расходы на хранение, т.к. tempdb в оперативке и чем больше откусишь ее, тем меньше останется для других пользователей/запросов)

    2. для каждой записи внешней таблицы ищем вхождение во вложенный датасет, тут вариант полный перебор или хэш джойн или еще что-то.

    3. в случае хэш джойн получим доп. накладные расходы на постороение хэш таблицы и на вычисление хэша для каждой записи внешней таблицы. Но есть плюс, т.к. вложенный датасет храниться в оперативке, то операции с ним выполняются быстрее чем с диском (хотя если диск SSD то разница не сильно большая).

    Вариант с not exist при наличии индекса:

    1. Тут возможна ситуация, что весь индекс или большая его часть закешированы в оперативке и тогда не будет множественных обращений к диску. А поиск в памяти по бинарному дереву (по индексу) может быть быстрее чем по хэш таблице, если учесть время необходимое для вычисления хэша от каждой записи внешней таблицы и на построение хэш таблицы.

    2. Если индекс не закеширован то да, на поиск и загрузку страниц индекса с диска требуется больше времени чем поиск в хэш таблице в оперативке.
  • Как получить список чисел отсутвующих в базе PostgreSQL?

    longclaps, Melkij, в данном случае not exists должен быть быстрее чем NOT IN.

    Тут фишка в том что при NOT IN нужно построить два датасета и заджойнить их, при этом по вложенному датасету в этом случае нет индекса и поиск будет долгим (возможно сервер сам примет решение сделать какой-нибудь hash join, но все равно это будут накладные расходы на построение хэш таблицы)

    Если использовать not exists и по полю id вложенной таблицы есть индекс, то вложенный подзапрос быстро отработает используя индекс для определения наличия id.(судя по описанию id это ключевое поле и индекс должен быть.)
  • Как правильно построить запрос из трех таблиц?

    Albert Kazan, вы правы. Но этот запрос простой как гвоздь.
    Вот как-то так:

    select t1.[id заказа], sum(t2.[Стоимость]) as total_price
      from СвязьТоваровЗаказов as t1
      inner join Товары as t2
                 on t2.[id] = t1.[id товара]
     group by t1.[id заказа]
  • Как правильно построить запрос из трех таблиц?

    Albert Kazan, тут есть нюанс. Если со временем у вас поменяется стоимость какого-то товара, то суммы всех заказов в которых есть этот товар изменятся, а значит и отчетность за прошлые периоды изменится. Но ведь по факту деньги за заказ заплатили фиксированные и стоимость уже оплаченного заказа меняться не должна. А ещё бывают всякие временные скидки и промокоды, которые не влияют на стоимость товара, но могут влиять на стоимость заказа. По хорошему после того как заказ сформирован общую сумму лучше хранить в заказе. И ещё для учета скидок и промокодов возможно потребуется добавить поле сумма в таблицу связи товаров и заказов. Т.к. например стоимость некоторых товаром может меняться от того сколько вы этих товаров (я имею ввиду количество) включили в заказ.
  • Как ускорить код с подсчетом похожести?

    Теоретически можно ещё запустить сравнение в несколько потоков.
  • Как правильно написать SQL запрос с использованием переменной?

    WebAnalytics1, странно все это, но вот если в вашем запросе правильно расставить алиасы у полей, то все работает, я вот такой запрос проверял:

    DECLARE @today as Date, @yesterday as Date;
    Set @today = convert(date, getdate());
    Set @yesterday = convert(date, dateadd(day, -1, getdate()));
    
    SELECT m.Name, o.Created,
    Count(DISTINCT(CASE WHEN Status =  'N' And  o.Date = @today Then i.ID END))  as NewQ,
    Count(DISTINCT(CASE WHEN Status =  'N' And  o.Date = @yesterday Then i.ID END))  as YdNewQ,
    Count(DISTINCT(CASE WHEN Status =  'W' And  o.Date = @today Then i.ID END)) as WaitingQ,
    Count(DISTINCT(CASE WHEN Status =  'W' And  o.Date = @yesterday Then i.ID END)) as YDWaitingQ,
    Count(DISTINCT(CASE WHEN Status =  'U' And  o.Date = @today Then i.ID END))  as ProblemQ,
    Count(DISTINCT(CASE WHEN Status =  'U' And  o.Date = @yesterday Then i.ID END))  as YdProblemQ,
    Count(DISTINCT(CASE WHEN Status =  'Z' And  o.Date = @today Then i.ID END))  as CancelledQ,
    Count(DISTINCT(CASE WHEN Status =  'Z' And  o.Date = @yesterday Then i.ID END))  as YdCancelledQ
    
    FROM Orders i 
    LEFT JOIN OrderItems o ON o.OrderID = i.ID
    LEFT JOIN NomenclUS m ON m.ID = o.ProductID
    
    WHERE i.Status <> 'Z' AND o.Created >= dateadd(day, -2, getdate())
    
    GROUP BY o.Created, m.CatID, m.CatName,m.Name
    ORDER BY o.Created, m.CatID


    Для эксперимента вот такие таблицы создал:
    create table Orders (ID int, Status varchar(1))
    go
    create table OrderItems (Created datetime, Date datetime, OrderID int, ProductID int)
    go
    create table NomenclUS(ID int, CatID int, CatName varchar(20), Name varchar(20))
    go
  • Что не так с полями БД?

    Sland Show, имена полей описаны в файле:
    spring-mvc-hibernate-mysql-integration-crud-example/src/main/java/com/javabycode/springmvc/model/Student.java

    у вас там идет описание полей:
    @Column(name = "NAME", nullable = false)
    или
    @Column(name = "nationality", nullable = false)
    и т. д.

    где-то name в верхнем регистре, где-то в нижнем.
  • Не работает код?

    А почему вы в SQL запросе не хотите вычесть эти 0,0002?

    например так:
    SELECT btc - 0.0002, * FROM users

    0,0002 лучше передать как параметр в запрос:
    SELECT btc - ?, * FROM users
  • Как упростить код заменяющий значения в словаре?

    Pavel Denisov, По хорошему да.
    Ну или как вариант понять, а точно ли нужно менять значение у ключа 'opcode',
    может проще начитать из БД (если это все из БД), расшифровку кода в отдельный ключ 'opcode_brief',
    тогда и словарь не потребуется.
  • Количество способов разбить n элементов на множества по 1, 5, 10 элементов?

    longclaps, Нет, порядок не важен, два подмножества содержащие одинаковые элементы равны и поэтому их не должно быть. Поэтому ваш вариант разбивки 6 элементов на 2 группы правильный, тут я тупанул.

    Тут логика даже проще, без перебора: 6 элементов можно разбить по 3 на 20 разных троек, но чтобы покрыть множество из 6 элементов нужны 2 тройки и поэтому разбивок группами по 3 элемента больше чем 10 при двух группах (3 +3 и 20/2 = 10) быть не может.

    И да формула в лоб не работает (C(n, k)), тут очень сильно влияет количество групп на которое нужно побить исходное множество, если их больше двух, то появляются дополнительные варианты по переносу элементов из группы в группу.

    Теперь по условию задачи, разбить на группы из 1, 5, 10 элементов можно только множество из числа элементов кратного 10 (иначе не выйдет целого количества групп), т.е. процедура определения количества разбиений должна выдавать результат только для чисел вида 10^n, для остальных чисел разбиение не определено.

    И теперь например для варианта, где n = 10, количество разбиений:
    группами по 1 элементу = 1
    группами по 10 элементов = 1
    группами по 5 элементов = 126
    (
    имеем 2 группы по 5 элементов
    Берем два опорных элемента 1 и 10, с ними получаем 2 варианта:
    вариант 1:
    группа 1 {1,_,_,_,_}
    группа 2 {10,_,_,_,_}

    Из оставшихся 8 элементов выбираем любые 4, это можно сделать C(8, 4) = 70 вариантов

    вариант 2:
    группа 1 {1,10,_,_,_}
    группа 2 {_,_,_ ,_,_}

    Из оставшихся 8 элементов выбираем любые 3, это можно сделать C(8, 3) = 56 вариантов

    Итого 70+56 = 126 вариантов
    )

    общее количество = 128

    Но если запустить вашу процедуру то получаем 9, как объяснить этот расчет?
  • Количество способов разбить n элементов на множества по 1, 5, 10 элементов?

    longclaps, И снова вы не все варианты учитываете, вот смотрите:
    Для опорного элемента {a} как уже выяснили 10 троек,
    но теперь берем опорный элемент {b} и считаем тройки
    {bcd} {bce} {bcf} {bde} {bdf} {bef} - т.е. еще 6 троек
    теперь берем опорный элемент {c}:
    {cde} {cdf} {cef} - еще 3 тройки
    и наконец опорный элемент{d}
    {def} - 1 тройка.
    В итоге 10 + 6 + 3 + 1 = 20, что и есть C(6, 3) = 20
  • Количество способов разбить n элементов на множества по 1, 5, 10 элементов?

    longclaps, Ок, давайте решим задачу в терминах этой вики.
    Дано множество {a, b, c, d, e, f}, требуется найти количество разбиений этого множества непересекающимися подмножествами состоящими из 2 элементов.

    Выбираем опорный элемент, например {a} и находим все возможные пары с этим элементом: {a, b},{a, c},{a, d},{a, e},{a, f} - всего 5 пар.
    Теперь для каждой пары находим количество разбиений из оставшихся 4 элементов.
    Например для пары {a, b} имеем такие варианты:
    Вариант 1- {c, d}, {e, f}
    Вариант 2- {c, e}, {d, f}
    Вариант 3- {c, f}, {d, e}

    Т.е. всего имеем 5 исходных пар умноженное на 3 разбиения для каждого, равно 15 возможных разбиений.
    Что как раз и есть C(6,2) =15
  • Количество способов разбить n элементов на множества по 1, 5, 10 элементов?

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

    Но тут опять же нужен автор вопрос, чтобы расставить точки на и.
  • Количество способов разбить n элементов на множества по 1, 5, 10 элементов?

    longclaps, вы пропустили часть вариантов, вот например для размера 2:
    ab, ac, ad, ae, af, bc, bd, be, bf, cd, ce, cf, de, df, ef
    C(6,2) = 720/(2*24) = 15

    решение как раз и дает 15.
  • Количество способов разбить n элементов на множества по 1, 5, 10 элементов?

    longclaps, Это скорее вопрос к автору вопроса.

    Тут каждый вариант разбиения независим от других.
    Если требуется сразу для 3 вариантов, то это будет сумма трех ранее найденных сочетания.
    Т.е. вот так:
    print(c(500, 1) + c(500, 5) + c(500, 10))

    Если взять простой пример (чтобы руками посчитать), например для n=10, то д.б.
    c(10, 1) = 10
    c(10, 5) = 252
    c(10, 10) = 1
    Общая сумма 263.