Лучший подход для хранения одного - многих отношения - практический пример/Дилемма

Я должен смоделировать идею, которая может ломаться и думаться следующим образом:

  1. BookDetails
  2. BookPrices

Проблема здесь состоит в том, что у Вас может быть много цен за книги, и эти цены, вероятно, изменятся. Вот пример

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

Это достаточно легко.

То, где это более интересно, - то, что для этой книги у меня могло бы быть десять различных цен в тот день, например:

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

Я должен предоставить список книг и всех их цен в столбцах - что-то как:

BookName         SpecialOffer   BulkPurchase      Normal    
Harry Potter…              10             20          30

Мой вопрос: таблица цены по прейскуранту должна на самом деле иметь все различные ценовые типы как столбцы? Мне это ужасно, и лучшая идея состоит в том, чтобы иметь каждую цену как строку

Если я использую тот подход, я не могу думать о SQL-запросе для генерации меня набор результатов. Я думал об этом все утро.

Править: У меня нет дрейфа при вычислении цен - они должны быть сохранены вниз.

Править: Это - в основном подход 1-n, я могу думать (Благодаря комментарию ниже) - что я на самом деле имел в виду

ВЫБЕРИТЕ book.bookid, bp1.price, bp2.price ИЗ книги bookprice bp2 СОЕДИНЕНИЯ bookprice bp1 СОЕДИНЕНИЯ НА bp1.bookid = book.bookid И bp1.pricetype=1 И bp2.bookid = book.bookid И bp2.pricetype=2...

Проблема за десять цен, к которым Вы будете присоединяться десять раз, который воняет!

6
задан Josh Kelley 8 February 2010 в 15:05
поделиться

10 ответов

Этот ответ специфичен для t-SQL и требует небольших уточнений, но он работает на SQL 2005.

Раскомментируйте закомментированные строки, и он обновится как MAGIC! (хорошо, не волшебство, но изящно хакерское)

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 

/ ** этот бит украден с 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)
4
ответ дан 8 December 2019 в 18:35
поделиться

как насчет этого

BookDetails
BookID BookName

BookPrice
BookID PriceID PriceTypeID

BookPriceType
PriceTypeID DEscription
5
ответ дан 8 December 2019 в 18:35
поделиться

Вопрос в следующем:

Будет ли список типов цен в книге статическим? или же типы цен (Columbus Day Price, Special Superbowl XXXVIII Price, Cause I like Tuesdays Price) будут часто появляться и исчезать?

Если список статичен (скажем, 5 или 6 различных типов цен), поместите каждый из них в дополнительный столбец в таблице продуктов.

Если список может измениться (хотя и незначительно и/или очень редко), добавьте отдельную таблицу для цен.

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

Что, черт возьми, мы делаем неправильно?

Вы делаете несколько усилий по развитию одной отрасли, и эти усилия не должны предприниматься одновременно (потому что их жизненный цикл отличается, т.е. они не будут выпущены одновременно)

Вы должны определить ветвь на разработку (а не на разработчика)и объединить эти филиалы в ветви предварительного выпуска (для интеграции всех утвержденных разработок для выпуска), с окончательным слиянием в Release, когда все разработки были проверены вместе.
Если каждая разработка является достаточно последовательной для каждого разработчика, это означает, что каждый разработчик может сохранить одну рабочую область для одной общей задачи и извлечь только соответствующую рабочую область для этого набора задач: количество файлов, фактически изменяющихся, будет небольшим, что значительно сократит время извлечения.

См.

-121--2814161-

Как уже упоминалось другими, если вы сохраняете данные в виде строк в своей таблице, у вас будет больше гибкости, если возникнет необходимость в большем количестве типов цен. Однако при использовании этого подхода, скорее всего, потребуется выполнить сведение данных для вывода результатов с одной строкой на книгу со всеми различными опциями ценообразования, включенными в одну строку (как следует из примера). В зависимости от используемой версии SQL Server это может быть относительно тривиальным для реализации, или это может быть немного сложнее. Для получения дополнительной информации см. Вопрос SO .

Если типы цен являются статичными, то лучше просто хранить данные в виде столбцов таблицы, а не в строках. Это делает тривиальным возврат данных в той форме, которую вы ищете, за счет того, чтобы быть немного больше работы, если правила изменятся.

2
ответ дан 8 December 2019 в 18:35
поделиться

Я много раз сталкивался с подобной проблемой . Я смотрю на это так: можете ли вы явным образом смоделировать книгу. Так, например, у вас есть 10 типов цен. Эти типы статичны? Они когда-нибудь меняются? Если они не меняются, я предпочитаю иметь их в виде столбцов в ценах (не назову это подробностями). Это будет включать эффективную дату начала и необязательную дату окончания. Это позволит вам заранее обрабатывать изменения цен.

Теперь, если вы не знаете, с какими ценами вы имеете дело. Примером может служить система, в которой конечный пользователь (скорее всего, пользователь-администратор) будет определять книги и различные типы цен. Это значительно более сложная система, потому что вам также нужно позволить пользователю определять правила, когда использовать какую цену.

Обновление

Вот пример использования динамического сводного запроса:

создать таблицу #BookPrice (bookId int, Price money, PriceType nvarchar (30)) вставить в #BookPrice {{1} } значения (1,10.55, 'List')

вставить в значения #BookPrice (1,9.50, 'Cost') вставить в значения #bookPrice (2 , 10.22, 'Список')

/ Выясните, какие цены вам нужны ....возможно, не путем запроса самой таблицы / объявления @priceQuery varchar (max) select @priceQuery = IsNull (@priceQuery, '') + '[' + cast (PriceType as varchar (32)) + '],' из (выберите отдельный PriceType из #BookPrice ) p

- Удалить последняя запятая установить @priceQuery = left (@ priceQuery, len (@priceQuery) -1)

объявить @dynquery varchar (max) установить @dynquery = 'select bookId, *' + 'from #BookPrice' + 'pivot (' + 'max ([Price])' + 'for [PriceType]' + {{1 }} 'in (' + @priceQuery + ')) as pivotTable'

exec (@dynquery)

drop table #bookPrice

UPDATE

Обновлен приведенный выше пример, чтобы показать, как, если у вас есть книга в котором отсутствует тип цены, который будет отображаться как null в запросе

1
ответ дан 8 December 2019 в 18:35
поделиться

Если вы хотите хранить цены статически (вместо например, вычисляя их), используйте отношение 1 к n:

Таблица 1 со строками: ID Название Издатель и т. д.

Таблица 2 со строками: BookID Цена

«BookID» из таблицы 2 будет указывать на «ID» из таблицы 1, таким образом вы можете иметь столько цен, сколько захотите . Используйте JOIN (см. SQL-документацию), чтобы получить все цены на конкретную книгу.

Если вы предлагаете специальные скидки (например, при оптовой покупке 10% скидка, но 20% скидка, если клиент покупает более 100 товаров за раз), я бы предпочел рассчитать цену, а не хранить ее статически.

0
ответ дан 8 December 2019 в 18:35
поделиться

Это базовый вариант использования таблицы моста, в которой у вас есть:

1 таблица для информации о книге
1 таблица для информации о ценах
1 таблица-мост для объедините их вместе для каждого экземпляра книги и цены.

0
ответ дан 8 December 2019 в 18:35
поделиться

Думаю, у меня была аналогичная проблема.
Я решил эту проблему с помощью конструкции t-sql 'pivot'
(уродство: вы должны явно указать столбцы в запросе)

Мы используем T -SQL.
Я не знаю диалекта sql, который вы используете, поэтому он может быть неприменим.

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

0
ответ дан 8 December 2019 в 18:35
поделиться

Возможно, это может сделать то, что вы хотите.

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]

Просто убедитесь, что имена столбцов соответствуют вашим, и он должен это делать. Кроме того, это ANSI, поэтому это не специфичный для СУБД код SQL DQL, и его можно использовать в ORACLE, SQL SERVER и т. Д.

0
ответ дан 8 December 2019 в 18:35
поделиться

Изменить: извините за неправильное прочтение вопроса

Здесь вы можете использовать три таблицы для представления вашей модели, одну для книг:

CREATE TABLE Books (
BookId Int,
Name Varchar
)

, одну для цен:

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

и одну, чтобы объединить их все вместе (у этого есть флаг чтобы показать текущую цену):

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

PriceName обеспечивает ловушку для сводного запроса, который превратит ваши строки в столбцы. В своем тесте я использовал имена Shelf и 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
ответ дан 8 December 2019 в 18:35
поделиться

Вопрос в следующем:

Будет ли список типов цен на книги статичным? Или типы цен (цена на День Колумба, специальная цена на Супербоул XXXVIII, цена за то, что я люблю вторники, будут часто появляться и исчезать?

Если список статичен (скажем, 5 или 6 различных типов цен, то поместите их каждый в дополнительный столбец в таблице продуктов.

Если список может меняться (пусть даже незначительно и/или очень редко), то добавьте отдельную таблицу для цен.

  Create Table Prices (
     ProductId Integer Not Null,
     PriceTypeId Integer Not Null,
     Price Decimal(16,4) Not Null,
     Primary Key Constraint PricePK (ProductId, PriceTypeId)
     )
1
ответ дан 8 December 2019 в 18:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: