想象一下,我是许多书店的老板。我保留了我所有书店中发生的所有事件的数据库。两个值得注意的事件是" Book Added"和#34; Book Removed",用于将图书添加到故事库存中以及何时从商店出售。示例模式为bookstore_id
,event_name
,`time。
现在说我有第二个表,它维护每个书店的当前状态,因此架构为bookstore_id
,num_books
。
我希望能够使用第一个表来计算所有" Book Added"每个书店的事件,减去所有" Book Removed"每个书店的事件,然后更新第二个表中每个书店的书籍数量。
我能想到的唯一方法就是使用光标,但我假设有一个更多" SQL-esque"这样做的方式更基于集合,并且不需要游标。
答案 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')
)
))
答案 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