2010-02-08 36 views
6

tôi cần để mô hình hóa một ý tưởng có thể được chia nhỏ và nghĩ đến như sau:Cách tiếp cận tốt nhất cho việc lưu trữ One-Nhiều mối quan hệ - thực tiễn Ví dụ/Dilemma

  1. BookDetails
  2. BookPrices

Vấn đề ở đây là bạn có thể có nhiều giá cho sách và những mức giá này có khả năng thay đổi. Dưới đây là ví dụ

 
BookDetails: 
----------------- 
ID Name 
1 Harry Potter… 

Điều này thật dễ dàng.

đâu nó là thú vị hơn là cho một cuốn sách này, tôi có thể có mười mức giá khác nhau trong ngày đó, ví dụ:

 
BookPrices: 
------------------------------------ 
Book_Details_Id Kind   Price 
1    SpecialOffer  10 
1    BulkPurchase  20 
1    Normal   30 

Tôi cần phải cung cấp một danh sách và tất cả giá của họ trong các cột - một cái gì đó như:

 
BookName   SpecialOffer BulkPurchase  Normal  
Harry Potter…    10    20   30 

Câu hỏi của tôi là: Bảng giá sách có thực sự có tất cả các loại giá khác nhau làm cột không? Đối với tôi điều này là xấu và ý tưởng tốt hơn là có mỗi giá là một hàng

Nếu tôi sử dụng cách tiếp cận đó, tôi không thể nghĩ ra truy vấn SQL để tạo cho tôi tập kết quả. Tôi đã nghĩ về điều này cả buổi sáng.

EDIT: Tôi không mất nhiều thời gian để tính giá - chúng phải được lưu trữ.

EDIT: Đây là cơ bản 1-n appraoch tôi có thể nghĩ đến (Nhờ bình luận dưới đây) - nó những gì tôi thực sự đã có trong tâm trí

CHỌN book.bookid, bp1.price, bp2.price TỪ cuốn sách THAM GIA bookprice bp1 JOIN bookprice bp2 ON bp1.bookid = book.bookid AND bp1.pricetype = 1 AND bp2.bookid = book.bookid AND bp2.pricetype = 2 ...

Vấn đề là cho mười giá bạn sẽ tham gia mười lần mà stinks!

+0

Bạn có thể cho chúng tôi biết yêu cầu cụ thể và cụ thể nào cho lược đồ bạn đang phát triển không? Một số câu hỏi: Bạn có cần phải có giá cụ thể cho mỗi cuốn sách không? Sẽ có nhiều loại ưu đãi? Các loại phiếu mua hàng có thay đổi thường xuyên không? –

+0

Tôi có quyền kiểm soát cách thể hiện điều này - tôi có thể chọn bảng 1-n (tôi thích làm) nhưng tôi không thể nghĩ cách tôi có thể lấy tất cả giá trong cột cho một cuốn sách. Cách khác là có mọi loại giá trong bảng và có một ánh xạ 1-1 –

+1

Bạn muốn có khả năng "** PIVOT **", SQL Server không hỗ trợ. SQL Server không thể tạo các cột như thế. –

Trả lời

4

Câu trả lời này là t-SQL cụ thể, và có thể sử dụng một chút tinh tế, nhưng nó hoạt động trên SQL 2005.

Bỏ ghi chú các dòng chú giải và nó sẽ cập nhật như MAGIC! (Okay, không kỳ diệu, nhưng niftily hacky)

DROP TABLE Books 
DROP TABLE Prices 
DROP TABLE bookpricing 

CREATE TABLE Books (id INT, title VARCHAR(20)) 
CREATE TABLE Prices (id INT, [desc] VARCHAR(20), pricingchange VARCHAR(20)) 
CREATE TABLE bookpricing (id INT, bookid INT, priceid INT, bookprice MONEY) 

INSERT INTO Books VALUES (1, 'Hi Mom') 
--INSERT INTO Books Values (2, 'This is another book') 
INSERT INTO Prices VALUES (1, 'Standard', '1') 
INSERT INTO Prices VALUES (2, 'Discount', '.5') 
INSERT INTO Prices VALUES(3, 'HyperMarkup', '1.5') 
INSERT INTO prices VALUES(4, 'Remaindered', '.1') 

INSERT INTO BookPricing VALUES (1,1,1,20.00) 
INSERT INTO BookPricing VALUES (2,1,2,10.00) 
INSERT INTO BookPricing VALUES (3,1,3,30.00) 
--INSERT INTO BookPricing VALUES (4,2,1,30.00) 
--INSERT INTO BookPricing VALUES (5,2,2,15.00) 
--INSERT INTO BookPricing VALUES (6,2,4,3.00) 

SELECT * FROM bookpricing 

/** bit này bị đánh cắp từ http://www.tsqltutorials.com/pivot.php **/

DECLARE @columns VARCHAR(max) 

SELECT @columns = COALESCE(@columns + ',[' + cast(id as varchar) + ']', 
'[' + cast(id as varchar)+ ']') 
FROM prices 


DECLARE @query VARCHAR(max) 

SET @query = ' 
SELECT * FROM (SELECT BookID, PriceID, BookPrice FROM BookPricing) AS BookTable PIVOT (SUM(bookprice) FOR priceid 
IN (' + @columns + ') 
) 
AS p' 

EXECUTE(@query) 
+2

Thật không may bất cứ lúc nào bạn cần thực hiện một trục trên một tập hợp các cột không xác định với các giá trị không xác định, bạn phải sử dụng SQL động. Ưu tiên của tôi là có một trình xem "proc builder" lấy các giá trị trong các hàng, kết hợp thành các bảng tổng hợp, sau đó giảm/tạo các khung nhìn dựa trên các giá trị mới Rất giống với những gì bạn đang làm ở đây, nhưng có hệ thống hơn – jcollum

+0

Công việc đó - Rất tốt! –

5

thế nào về vấn đề này

BookDetails 
BookID BookName 

BookPrice 
BookID PriceID PriceTypeID 

BookPriceType 
PriceTypeID DEscription 
+0

Ok - Whats truy vấn để hiển thị cho tôi tất cả giá (ngay cả khi null) cho một cuốn sách? Thats phần khó khăn –

+0

Điều này có mùi rất nhiều như bài tập về nhà. – Tomalak

+2

Nó chắc chắn không phải là - Câu hỏi của tôi là làm thế nào tôi có thể đại diện cho điều này như mối quan hệ 1-n và hút ra tất cả các giá như COLUMNS –

0

Nếu bạn muốn để lưu trữ các giá tĩnh (thay vì ví dụ như tính toán chúng), sử dụng một 1-to-n-liên quan:

Bảng 1 với hàng: ID Tiêu đề Publisher , vv

Bảng 2 với hàng: BookID Giá

"BookID" từ Bảng 2 sẽ trỏ đến "ID" từ Bảng 1, theo cách này bạn có thể có bao nhiêu giá tùy thích. Sử dụng JOIN (xem tài liệu SQL) để lấy tất cả giá cho một cuốn sách cụ thể.

Nếu bạn cung cấp giảm giá đặc biệt (ví dụ: mua hàng loạt 10%, nhưng giảm 20% nếu khách hàng mua nhiều hơn 100 mặt hàng cùng một lúc), tôi muốn tính giá thay vì lưu trữ tĩnh.

+0

Sử dụng 3 bảng (như được đề xuất trong các câu trả lời khác) chỉ cần thiết, nếu bạn muốn sử dụng lại giá cho các sách khác (một giá chỉ được lưu trữ một lần). Nhưng theo cách này, bạn sẽ thay đổi giá cụ thể đó cho TẤT CẢ sách nếu bạn sửa đổi nó. – Select0r

0

Đây là trường hợp sử dụng cơ bản cho một bảng cầu nơi bạn có:

1 bảng để biết cuốn sách
1 bảng để biết giá
bảng 1 cây cầu để tham gia hai cùng nhau cho mỗi trường hợp của cuốn sách và giá bán.

1

Tôi đã gặp phải vấn đề tương tự này nhiều lần. Cách tôi nhìn vào nó, bạn có thể mô hình hóa một cuốn sách một cách rõ ràng không. Vì vậy, ví dụ bạn có 10 loại giá. Các loại này có tĩnh không? Họ có bao giờ thay đổi không? Nếu họ không thay đổi thì tôi muốn có chúng như cột, trong một giá cả (sẽ không gọi nó là chi tiết). Điều đó sẽ bao gồm ngày bắt đầu có hiệu lực và ngày kết thúc tùy chọn. Điều này sẽ cho phép bạn xử lý các thay đổi giá dàn dựng trước thời hạn.

Bây giờ, nếu bạn không biết loại giao dịch của mình. Một ví dụ sẽ là một hệ thống mà người dùng cuối (Người dùng Quản trị viên nhiều khả năng nhất) sẽ xác định sách và các loại giá khác nhau. Đây là một hệ thống phức tạp hơn đáng kể bởi vì bạn cũng cần phải cho phép người dùng xác định các quy tắc xung quanh khi nào sử dụng giá nào.

Cập nhật

Dưới đây là một ví dụ của việc sử dụng một truy vấn trục động:

tạo bảng #BookPrice (bookId int, tiền Giá, PriceType nvarchar (30)) chèn vào #BookPrice giá trị (1,10.55, 'Danh sách')

chèn vào #BookPrice giá trị (1,9.50, 'Chi phí') chèn vào #bookPrice giá trị (2,10.22, 'Danh sách')

/Hình ra mức giá mà bạn cần .... probally không bởi truy vấn bảng chính nó/ khai báo @priceQuery varchar (max) chọn @priceQuery = IsNull (@priceQuery, '') + '[ '+ dàn diễn viên (PriceType như varchar (32)) + '],' từ (chọn PriceType biệt từ #BookPrice ) p

- Hủy bỏ dấu phẩy cuối cùng thiết @priceQuery = left (@ priceQuery, len (@priceQuery) -1)

khai báo @dynq uery varchar (max) bộ @dynquery = 'chọn bookId, *' + 'từ #BookPrice' + 'trục (' + 'max ([Giá])' + 'cho [PriceType]' + ' trong (' + @priceQuery + ')) như PivotTable'

exec (@dynquery)

thả bảng #bookPrice

CẬP NHẬT

Updated ví dụ trên để hiển thị ho w nếu bạn có một cuốn sách mà thiếu loại giá rằng nó sẽ hiển thị như null trong truy vấn

+0

Thats chính xác vấn đề ở đây - Tôi có thể có giá MANY cho một cuốn sách và thats những gì tôi không thể mô hình –

1

Câu hỏi đặt ra ở đây là:

Wil danh sách lthe của Sách Giá các loại được tĩnh?hoặc là các loại giá (Giá ngày Columbus, Giá đặc biệt Superbowl XXXVIII, Nguyên nhân tôi thích thứ Ba Giá, thường xuyên xuất hiện và biến mất?

Nếu danh sách là tĩnh, (nói 5 hoặc 6 loại giá khác nhau, sau đó đặt họ từng trong một cột bổ sung trong bảng sản phẩm.

Nếu danh sách có thể thay đổi (thậm chí nếu chỉ hơi và/hoặc rất hiếm) sau đó thêm một bảng riêng biệt cho các giá.

Create Table Prices (
    ProductId Integer Not Null, 
    PriceTypeId Integer Not Null, 
    Price Decimal(16,4) Not Null, 
    Primary Key Constraint PricePK (ProductId, PriceTypeId) 
    ) 
2

Như những người khác có được đề cập, nếu bạn lưu trữ dữ liệu dưới dạng các hàng trong bảng của mình, bạn sẽ linh hoạt hơn nếu cần phải có nhiều loại giá phát sinh hơn. sử dụng phương pháp này rất có thể sẽ yêu cầu bạn Xoay vòng dữ liệu để xuất kết quả với một hàng cho mỗi sách với tất cả các tùy chọn đặt giá khác nhau được bao gồm trên cùng một hàng (như ví dụ của bạn ngụ ý). Tùy thuộc vào phiên bản của SQL Server bạn đang sử dụng này có thể là tương đối tầm thường để thực hiện, hoặc nó có thể nhiều hơn một chút khó khăn hơn. Xem chi tiết SO question để biết thêm chi tiết.

Nếu các loại giá là tĩnh thì bạn có thể được phục vụ tốt hơn chỉ đơn giản là lưu trữ dữ liệu dưới dạng cột của bảng thay vì theo hàng. Điều này làm cho nó tầm thường để trả lại dữ liệu trong biểu mẫu bạn đang tìm kiếm, với chi phí là một công việc nhiều hơn một chút nên các quy tắc thay đổi.

0

Edit: Xin lỗi vì hiểu sai câu hỏi

Bạn có thể sử dụng ba bảng ở đây để đại diện cho mô hình mà bạn, một cho cuốn sách:

CREATE TABLE Books (
BookId Int, 
Name Varchar 
) 

một cho giá:

CREATE TABLE Prices (
PriceId Int, 
Amount decimal, 
PriceName varchar 
) 

và một để tham gia cùng nhau (điều này có một lá cờ để hiển thị giá hiện tại):

CREATE TABLE BookPrices (
BookId Int, 
PriceId Int, 
Current bit 
) 

PriceName cung cấp một móc cho truy vấn trục, sẽ chuyển hàng của bạn thành các cột. Trong thử nghiệm của tôi, tôi đã sử dụng tên Shelf và Online

SELECT * 
FROM (
    SELECT Book.Name BookName, Price.Amount Amount, Price.Name PriceName 
    FROM Books Book 
    JOIN BookPrices bp 
     ON Book.BookId = bp.BookId 
    JOIN Prices Price 
     ON Price.PriceId = bp.PriceId 
) DataTable 
PIVOT(
    SUM(Amount) 
    FOR PriceName IN ([Shelf],[Online]) 
) PivotTable 
+0

Điều đó mang lại cho tôi giá như ROWS !! Tôi cần chúng như các cột: ( –

0

Tôi nghĩ rằng tôi đã có vấn đề tương tự.
tôi giải quyết này với t-sql xây dựng 'trục'
(xấu xa: bạn phải nói rõ các cột trong truy vấn)

Chúng tôi đang sử dụng T-SQL.
Tôi không biết phương ngữ sql bạn đang sử dụng, vì vậy có thể không áp dụng được.

http://www.tsqltutorials.com/pivot.php

0

này có lẽ có thể làm những gì bạn muốn.

SELECT D.ID, D.[NAME] 
, SUM(D.SpecialOffer) AS SpecialOffer 
, SUM(D.BulkPrice) AS BulkPrice 
, SUM(D.Normal) AS Normal 
FROM (
SELECT BD.ID AS ID, BD.NAME AS [NAME] 
    , CASE WHEN BP.Kind LIKE N'%SpecialOffer%' THEN BP.Price ELSE NULL END AS SpecialOffer 
    , CASE WHEN BP.Kind LIKE N'%BulkPrice%' THEN BP.Price ELSE NULL END AS BulkPrice 
    , CASE WHEN BP.Kind LIKE N'%Normal%' THEN BP.Price ELSE NULL END AS Normal 
FROM BookDetails BD 
INNER JOIN BookPrices BP ON BP.ID_BOOK_DETAILS = BD.ID) D 
GROUP BY D.ID, D.[NAME] 

Chỉ cần đảm bảo tên cột phù hợp với tên của bạn và nó nên thực hiện. Hơn nữa, nó là ANSI, vì vậy đây không phải là mã DQL SQL cụ thể DBMS và có thể được sử dụng trên ORACLE, SQL SERVER, v.v.

Các vấn đề liên quan