SQL查询根据事件名称更新对象计数

时间:2016-03-16 20:09:25

标签: sql sql-server tsql qsqlquery

想象一下,我是许多书店的老板。我保留了我所有书店中发生的所有事件的数据库。两个值得注意的事件是" Book Added"和#34; Book Removed",用于将图书添加到故事库存中以及何时从商店出售。示例模式为bookstore_idevent_name,`time。

现在说我有第二个表,它维护每个书店的当前状态,因此架构为bookstore_idnum_books

我希望能够使用第一个表来计算所有" Book Added"每个书店的事件,减去所有" Book Removed"每个书店的事件,然后更新第二个表中每个书店的书籍数量。

我能想到的唯一方法就是使用光标,但我假设有一个更多" SQL-esque"这样做的方式更基于集合,并且不需要游标。

7 个答案:

答案 0 :(得分:1)

select bookstore_id
     , sum(case when event_name = "Book Removed" then -1 else 1 end) as "num books"
  from bookstores  
 group by bookstore_id 

如果超过2个事件

select bookstore_id
     , sum(case when event_name = "Book Removed" then -1 
                when event_name = "Book Added"   then  1  
           end) as "num books"
  from bookstores  
 group by bookstore_id 

除非你提出性能问题,否则我会把它作为一个观点

答案 1 :(得分:1)

您可以使用GROUP BY子句对事件进行计数。

如果我们创建2个子表,我们计算分别添加已删除的书籍,我们可以简单地减去结果并在父表中更新它们。这看起来像是:

UPDATE      b
SET         b.numbooks = AddedBooks.BooksAdded - RemovedBooks.BooksRemoved
FROM        dbo.Books b
INNER JOIN  (SELECT     be.book_id, count(*) AS BooksAdded
            FROM        dbo.BookEvents be
            WHERE       be.event = 'BookAdded'
            GROUP BY    be.book_id, be.event) AS AddedBooks 
                                    ON b.bookid = AddedBooks.book_id
INNER JOIN  (SELECT     be.book_id, count(*) AS BooksRemoved
            FROM        dbo.BookEvents be
            WHERE       be.event = 'BookRemoved'
            GROUP BY    be.book_id, be.event) AS RemovedBooks  
                                    ON b.bookid = RemovedBooks.book_id

答案 2 :(得分:0)

我们可以使用CTE单独获取详细信息并进行处理。

With CTE_Add AS
(
Select Bkstr_ID, Count(event_Name) As Added From temp Where event = 'Added' Group by Bkstr_ID
), CTE_Rem As
(
Select Bkstr_ID, Count(event_Name) As Removed From temp Where event = 'Removed'      Group by Bkstr_ID
)
Select A.Bkstr_ID,  Added - Removed
From CTE_Add A
Left Join CTE_Rem R On A.Bkstr_ID= R.Bkstr_ID

这将为您提供ID和计数。 您可以使用Insert语句

而不是select

答案 3 :(得分:0)

我使用SUM(CASE WHEN ...)。以下是一个例子。

If object_id('tempdb..#BoookStores') Is Not Null Drop Table #BoookStores
Create Table #BoookStores (bookstore_id int, num_books int)

/* We have 3 stores */
Insert #BoookStores (bookstore_id, num_books)
Values  (1, 0), (2, 0), (3, 0)

If object_id('tempdb..#Events') Is Not Null Drop Table #Events
Create Table #Events (bookstore_id int, event_name varchar(10), time dateTime Default(GetDate()) )

Insert #Events (bookstore_id, event_name)
Values
(1, 'Added'), (1, 'Added'), (1, 'Added'), (1, 'Added'), -- Added 4 books to 1. store
(2, 'Added'), (2, 'Added'), (2, 'Added'), -- Added 3 books to 2. store
(3, 'Added'), (3, 'Added'), -- Added 2 books to 3. store

/* removed 2 books from each stores */
(1, 'Removed'), (1, 'Removed'), 
(2, 'Removed'), (2, 'Removed'),
(3, 'Removed'), (3, 'Removed')

/* Calculate adds and removes. Update the results */
;With Tmp As (
    Select  E.bookstore_id,
            Sum(Case When E.event_name = 'Added' Then 1 Else 0 End) As AddCount,
            Sum(Case When E.event_name = 'Removed' Then 1 Else 0 End) As RemoveCount
    From    #Events E
    Group By E.bookstore_id
)
Update  BS Set num_books = T.AddCount-T.RemoveCount
From    #BoookStores BS
        Inner Join Tmp T On T.bookstore_id = BS.bookstore_id 

/* check results*/
Select * From #BoookStores BS

答案 4 :(得分:0)

这样的事情会让你进入球场。类似的逻辑可以用于INSERT。

UPDATE tableA
SET tableA.num_books = tableB.num_books
FROM secondTable AS TableA
INNER JOIN (
    SELECT bookstore_id,
        SUM(CASE 
                WHEN event_name = 'Books Added'
                    THEN 1
                END) - SUM(CASE 
                WHEN event_name = 'Books Removed'
                    THEN 1
                END
            ) AS num_books
    FROM firstTable
    GROUP BY bookstore_id
    ) TableB ON TableA.bookstore_id = tableB.bookstore_id

答案 5 :(得分:0)

您可以尝试以下查询:

library(shiny)
library(ggplot2)
library(dplyr)


dataset <- iris

shinyUI(pageWithSidebar(

  headerPanel("Iris Data Explorer"),

  sidebarPanel(


    selectInput('x', 'X', names(dataset), names(dataset)[[2]]),
    selectInput('y', 'Y', names(dataset), names(dataset)[[4]]),
    selectInput('offset', 'Offset Level of Y', 0:5, 0),
    selectInput('species', 'Species', levels(dataset$Species), "virginica")
  ),

  mainPanel(
    plotOutput('plot')
  )
))

Live SQL demo

答案 6 :(得分:0)

UPDATE  bsc
SET     bsc.num_books = bse.num_books
FROM    bookstorecounts bsc
        JOIN (SELECT    bookstore_id,
                        SUM(CASE event_name
                              WHEN 'Book Removed' THEN -1
                              WHEN 'Book Added' THEN 1
                            END) AS num_books
              FROM      bookstoreevents
              GROUP BY  bookstore_id
        ) bse ON bsc.bookstore_id = bse.bookstore_id