2017-07-12 71 views
0

假設我有一張表格,對於每個新的「Item Bought」,它都會重新創建一個包含除New Item之外的所有相同值的行,並且有1000個不同的項目。SQL Server中的壓縮行

ID  Time Date  Cashier Item Bought  
0001 12:00 16/1/26  Bob  Apple 
0001 12:00 16/1/26  Bob  chicken 
0001 12:00 16/1/26  Bob  eggs 
0001 12:00 16/1/26  Bob  Banana 
0002 12:30 16/1/27  Steve Apple 
0002 12:30 16/1/27  Steve pork 
0002 12:30 16/1/27  Steve milk 

我想要做的是以節省空間的方式壓縮行,但仍允許我按項目搜索交易。

事情我想

位操作

分配每每一位到項目。

Item Bit 
Apple 1 (0000 0001) 
eggs 2 (0000 0010) 
Chicken 3 (0000 0100) 
fish 4 
Banana 5 
pork 6 
milk 7 
. 
. 
. 
(to 1000) 

變化

ID  Time Date  Cashier Item Bought 
0001 12:00 16/1/26  Bob  Apple 
0001 12:00 16/1/26  Bob  chicken 
0001 12:00 16/1/26  Bob  eggs 
0001 12:00 16/1/26  Bob  Banana 

進入

ID  Time Date  Cashier  Items Bought      
0001 12:00 16/1/26  Bob   0001 0111 

我能做到位操作,以檢查項目。

檢查事務具有蘋果和香蕉

0001 0111 Items Bought 
0001 0001 Check = bits for apple and banana 

邏輯:如果(〜檢查項目也不買== 0)(含)

1110 1110 ~Check 
0001 0111 Items Bought 

0000 0000 

問題是,你只能做位運算起來到BIGINT的64位。我需要1000位或16個額外的列。

素數

分配基於一個項目是如何頻繁的買

Item Bought Assigned Prime 
Apple 190893 2 
eggs 150022 3 
Chicken 71026 5 
fish 59827 7 
Banana 10274 11 
pork 5271 13 
milk 1021 17 
. 
. 
. 
(to 1000) 

對於每一列乘以每總理一起

變化

ID  Time Date  Cashier Item Bought 
0001 12:00 16/1/26  Bob  Apple 
0001 12:00 16/1/26  Bob  chicken 
0001 12:00 16/1/26  Bob  eggs 
0001 12:00 16/1/26  Bob  Banana 
0002 12:30 16/1/27  Steve Apple 
0002 12:30 16/1/27  Steve pork 
0002 12:30 16/1/27  Steve milk 

質數到

ID  Time Date  Cashier  Items Bought 
0001 12:00 16/1/26  Bob   330 (2 * 5 * 3 * 11) 
0002 12:30 16/1/27  Steve  442 (2 * 13 * 17) 

如果我想查看哪些交易有一個項目,請將該列除以該素數。通過素數的屬性,如果結果是一個整數,則交易確實具有該項目。

檢查事務具有蘋果,香蕉

primeCheck = 22(2 * 11)

邏輯:如果(產品購買%primeCheck == 0)(包含)

ID  Time Date  Cashier  Include 
0001 12:00 16/1/26  Bob   YES  330 % 22 = 0 
0002 12:30 16/1/27  Steve  NO  442 % 22 = 2 

問題是,乘以素數真的很快。爲什麼我會用這個比特操作的原因是,對於BM,無論項目如何,我都需要1024位。

字符串拼接

變化

ID  Time Date  Cashier Item Bought 
0001 12:00 16/1/26  Bob  Apple 
0001 12:00 16/1/26  Bob  chicken 
0001 12:00 16/1/26  Bob  eggs 
0001 12:00 16/1/26  Bob  Banana 

進入

ID  Time Date  Cashier  Items Bought      
0001 12:00 16/1/26  Bob   Apple, chicken, eggs, Banana  

問題是搜索複雜遍歷每個項目買串。

有什麼建議嗎?

+1

這對我來說根本沒有意義。您是否試圖創建一個以逗號分隔的物品編號清單?還是其他什麼東西?這聽起來像是一個典型的XY問題。 –

+0

我認爲你應該表達你正在嘗試做什麼的邏輯,並讓SQL引擎處理低級細節。 –

+0

啊,我明白了。好,讓我解決我的問題。在要點中,我試圖以我節省時間和計算的方式來濃縮我的表格 –

回答

0

爲什麼不簡單地標準化表結構? 類似以下內容或許...

USE tempdb; 
GO 

CREATE TABLE dbo.Personnel (
    PersonID INT NOT NULL 
     CONSTRAINT pk_Personnel_PersonID PRIMARY KEY CLUSTERED (PersonID), 
    PersonName VARCHAR(50) NOT NULL 
    ); 

CREATE TABLE dbo.Product (
    ProductID INT NOT NULL 
     CONSTRAINT pk_Product_ProductID PRIMARY KEY CLUSTERED (ProductID), 
    ProductName VARCHAR(50) NOT NULL 
    ); 

CREATE TABLE dbo.OrderHeader (
    OrderHeaderID INT NOT NULL 
     CONSTRAINT pk_OrderHeader_OrderHeaderID PRIMARY KEY CLUSTERED (OrderHeaderID), 
    OrderDT DATETIME2(0) NOT NULL 
     CONSTRAINT df_OrderHeader_OrderDT DEFAULT (GETDATE()), 
    CashierID INT NOT NULL 
     CONSTRAINT fk_OrderHeader_Personnel_PersonID FOREIGN KEY REFERENCES dbo.Personnel(PersonID) 
    ); 

CREATE TABLE dbo.OrderDetail (
    OrderDetailID INT NOT NULL 
     CONSTRAINT pk_OrderDetail_OrderDetailID PRIMARY KEY CLUSTERED (OrderDetailID), 
    OrderHeaderID INT NOT NULL 
     CONSTRAINT fk_OrderDetail_OrderHeader_OrderHeaderID FOREIGN KEY REFERENCES dbo.OrderHeader(OrderHeaderID), 
    ProductID INT NOT NULL 
     CONSTRAINT fk_OrderDetail_Product_ProductID FOREIGN KEY REFERENCES dbo.Product(ProductID), 
    Quantity INT NOT NULL 
     CONSTRAINT df_OrderDetail_Quantity DEFAULT (1), 
    Returned BIT NOT NULL 
     CONSTRAINT df_OrderDetail_Returned DEFAULT(0) 
    ); 

INSERT dbo.Personnel (PersonID, PersonName) VALUES (1, 'Bob'); 

INSERT dbo.Product (ProductID, ProductName) VALUES 
    (1, 'Apple'), (2, 'Chicken'), (3, 'Eggs'), 
    (4, 'Banana'), (5, 'Pork'), (6, 'Milk'); 

INSERT dbo.OrderHeader (OrderHeaderID, OrderDT, CashierID) VALUES 
    (1, '2016-01-26 12:00:00', 1), (2, '2016-01-26 12:00:00', 1); 

INSERT dbo.OrderDetail (OrderDetailID, OrderHeaderID, ProductID, Quantity, Returned) VALUES 
    (1, 1, 1, 1, 1), (2, 1, 2, 1, 0), (3, 1, 3, 12, 0), (4, 1, 4, 1, 0), 
    (5, 2, 1, 2, 0), (6, 2, 5, 1, 1), (7, 2, 6, 1, 0); 

--=============================================================== 

-- query that produces the original data... 
SELECT 
    oh.OrderHeaderID, 
    [Time] = CAST(oh.OrderDT AS TIME), 
    [Date] = CAST(oh.OrderDT AS DATE), 
    Cashier = p.PersonName, 
    ItemBought = p2.ProductName, 
    od.Returned 
FROM 
    dbo.OrderHeader oh 
    JOIN dbo.OrderDetail od 
     ON oh.OrderHeaderID = od.OrderHeaderID 
    JOIN dbo.Personnel p 
     ON oh.CashierID = p.PersonID 
    JOIN dbo.Product p2 
     ON od.ProductID = p2.ProductID;