Создание запроса SQL, который выполняет математику с переменными из нескольких таблиц - PullRequest
1 голос
/ 16 февраля 2011

Вот пример того, что я пытался сделать до сих пор:

Макет таблицы:

Инвентарь

ID  |  lowrange  |  highrange
-------------------------------
1   |  15        |  20
2   |  21        |  30

Аудит (не используетсяв этом запросе помимо объединения)

MissingOrVoid

ID  |  Item  |  Missing  |  Void
---------------------------------
1   |  17    |   1       |  0
1   |  19    |   1       |  0

Самый последний запрос, который я пытался использовать:

SELECT    I.*,
          SUM(
              (I.HIGHRANGE - I.LOWRANGE + 1)
              - (Count(M.Missing) from M where M.ID = I.ID)
              - (Count(M.Void) from M where M.ID = I.ID)) AS Item_Quantity


FROM Inventory I 
    JOIN Audit A 
        ON A.ID = I.ID 
    JOIN MissingOrVoid M 
        ON M.ID = I.ID

Результат должен быть:

ID  |  lowrange  |  highrange  |  Item_Quantity
-----------------------------------------------
1   |  15        |  20         |  4
2   |  21        |  30         |  10

Не могу точно вспомнить, где я внес изменения, но в предыдущей попытке ранее было получено сообщение об ошибке: «Невозможно выполнить агрегатную функцию для выражения, содержащего агрегат или подзапрос».В настоящее время ошибка имеет неправильный синтаксис рядом с «from» (тот, что находится рядом с M.Missing, но, насколько я знаю, по минимальным знаниям SQL, эти синтаксические проблемы вызывают явный сбой, и могут существовать основные проблемы с запросом, которые не видны довсе проблемы с синтаксисом исправлены).

Часть, на которой я действительно бомбардирую, это, очевидно, секция SUM ().Я далек от архитектора баз данных, поэтому кто-то может объяснить, как правильно выполнить это, и, возможно, указать мне направление к ресурсу, чтобы узнать об этом типе функции?

Спасибо

Ответы [ 6 ]

2 голосов
/ 16 февраля 2011

Вы почти поняли это правильно. Я предполагаю, что пропущенные / недействительные являются типами БИТ, которые вы не можете СУММИТЬ напрямую.

SELECT I.*,
    (I.HIGHRANGE - I.LOWRANGE + 1)
    - (select Count(nullif(M.Missing,0)) from MissingOrVoid M where M.ID = I.ID)
    - (select Count(nullif(M.Void,0)) from MissingOrVoid M where M.ID = I.ID)
    AS Item_Quantity
FROM Inventory I 

Если элемент не может быть пропущен и аннулирован, тогда

SELECT I.*,
       I.HIGHRANGE - I.LOWRANGE + 1
           - (select Count(case when M.Missing=1 or M.Void=1 then 1 end)
              from MissingOrVoid M where M.ID = I.ID)
           AS Item_Quantity
FROM Inventory I

На самом деле, если он присутствует только в MissingOrVoid, когда он отсутствует или недействителен, тогда CASE в приведенном выше запросе всегда будет истинным, поэтому это упрощается до

SELECT I.*,
       I.HIGHRANGE - I.LOWRANGE + 1
           - (select Count(*) from MissingOrVoid M where M.ID = I.ID)
           AS Item_Quantity
FROM Inventory I
0 голосов
/ 16 февраля 2011

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

SELECT I.*,        
I.HIGHRANGE - I.LOWRANGE + 1 -  MissingVoidCount AS Item_Quantity 
FROM Inventory I  
JOIN 
    (SELECT ID,Count(*) AS MissingVoidCount FROM MissingOrVoid GROUP BY ID) M
        on M.ID = I.ID

Конечно, в реальной жизни я бы никогда не использовал select *,Вы также можете использовать подход CTE.

    ;WITH  MissingVoid(ID, MissingVoidCount) AS
    (
        SELECT ID, Count(*)  FROM MissingOrVoid GROUP BY ID
    )
    SELECT 
        I.*,        
        I.HIGHRANGE - I.LOWRANGE + 1 -  MissingVoidCount AS Item_Quantity 
    FROM Inventory I
    JOIN MissingVoid M
        on M.ID = I.ID
0 голосов
/ 16 февраля 2011

Я бы сказал, что это будет работать:

SELECT  I.ID,I.Lowrange as Lowrange,
        I.highrange as Highrange,
        Highrange-Lowrange+1-COUNT(J.missing)-COUNT(J.void) AS ITEM_QUANTITY 
FROM Inventory I
left JOIN  ( select missing as missing, void as void, id from MissingOrVoid 
            ) J
    ON I.ID = J.Id
JOIN Audit A 
    ON A.ID = I.ID          
GROUP BY I.ID,Highrange,Lowrange

Но похоже, что RemoteSojourner много предлагал (и его тоже более эстетично).

0 голосов
/ 16 февраля 2011

Следующий запрос работает.Предполагается, что для каждого идентификатора есть только один верхний и нижний диапазон.

CREATE TABLE #Inventory (ID INT,Lowrange INT,highrange INT)
CREATE TABLE #MissingOrVoid (Id INT,item INT, missing INT, void INT)

INSERT #Inventory
        ( ID, Lowrange, highrange )
VALUES  ( 1, -- ID - int
          15, -- Lowrange - int
          20  -- highrange - int
          )
INSERT #Inventory
        ( ID, Lowrange, highrange )
VALUES  ( 2, -- ID - int
          21, -- Lowrange - int
          30  -- highrange - int
          )
INSERT #MissingOrVoid
        ( Id, item, missing, void )
VALUES  ( 1, -- Id - int
          17, -- item - int
          1, -- missing - int
          0  -- void - int
          )
INSERT #MissingOrVoid
        ( Id, item, missing, void )
VALUES  ( 1, -- Id - int
          19, -- item - int
          1, -- missing - int
          0  -- void - int
          )


SELECT #Inventory.ID,
       #Inventory.highrange,
       #Inventory.Lowrange,
       highrange-Lowrange+1
           -SUM(ISNULL(missing,0))
           -SUM(ISNULL(void,0)) AS ITEM_QUANTITY
FROM #Inventory
left JOIN  #MissingOrVoid ON #Inventory.ID = #MissingOrVoid.Id
GROUP BY #Inventory.ID,#Inventory.highrange,#Inventory.Lowrange


DROP TABLE #Inventory
DROP TABLE #MissingOrVoid
0 голосов
/ 16 февраля 2011

Это то, что вы пытаетесь сделать?Я не уверен, каковы числа в пропущенных и пустых столбцах, если они не просто флаги ...

SELECT    I.*,
          ((I.highrange - I.lowrange + 1)
              - SUM(M.Missing)
              - SUM(M.Void)) AS Item_Quantity


FROM Inventory I 
    JOIN MissingOrVoid M 
        ON M.ID = I.ID
0 голосов
/ 16 февраля 2011

Изначально у меня возник вопрос, нужно ли вам суммировать эти значения.Если в вашей таблице инвентаря есть по одной строке на предмет, в этом нет необходимости.Я предполагаю, что в вашей таблице может быть несколько строк для данного элемента, и продолжу оттуда.Я не проверял это, но я думаю, что это должно выглядеть примерно так:

select I.ID, 
    I.Item, 
    SUM(I.HighRange - I.LowRange + 1)
    - (
        select SUM(M.Missing + M.Void)
        from dbo.Audit A
        where A.ID = I.ID
      )
from Inventory I
group by I.ID, I.Item
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...