2017-07-12 14 views
0

テーブルを作成して、新しい「アイテム購入」ごとに、新しいアイテムを除くすべての同じ値を持つ行を再作成し、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  Items Bought      
0001 12:00 16/1/26  Bob   0001 0111 

に変わり

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 

私はアイテムをチェックするためにビット演算を行うことができます。

チェックトランザクションはリンゴとバナナ

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の追加の列が必要になります。

素数

はアイテムがすべての

一緒プライム変更

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 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) 

を買っているか、頻繁に基づいて素数を割り当てTo

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(* 11 2)

ロジックがある場合:

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 

(アイテム%primeCheck == 0を買った)(含める)場合は、問題を素数を掛けることは本当に速くなります。私がビット操作を使ってこれを使う理由は、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;