Я должен смоделировать идею, которая может ломаться и думаться следующим образом:
Проблема здесь состоит в том, что у Вас может быть много цен за книги, и эти цены, вероятно, изменятся. Вот пример
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...
Проблема за десять цен, к которым Вы будете присоединяться десять раз, который воняет!
Этот ответ специфичен для 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)
как насчет этого
BookDetails
BookID BookName
BookPrice
BookID PriceID PriceTypeID
BookPriceType
PriceTypeID DEscription
Вопрос в следующем:
Будет ли список типов цен в книге статическим? или же типы цен (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, когда все разработки были проверены вместе.
Если каждая разработка является достаточно последовательной для каждого разработчика, это означает, что каждый разработчик может сохранить одну рабочую область для одной общей задачи и извлечь только соответствующую рабочую область для этого набора задач: количество файлов, фактически изменяющихся, будет небольшим, что значительно сократит время извлечения.
См.
Как уже упоминалось другими, если вы сохраняете данные в виде строк в своей таблице, у вас будет больше гибкости, если возникнет необходимость в большем количестве типов цен. Однако при использовании этого подхода, скорее всего, потребуется выполнить сведение данных для вывода результатов с одной строкой на книгу со всеми различными опциями ценообразования, включенными в одну строку (как следует из примера). В зависимости от используемой версии SQL Server это может быть относительно тривиальным для реализации, или это может быть немного сложнее. Для получения дополнительной информации см. Вопрос SO .
Если типы цен являются статичными, то лучше просто хранить данные в виде столбцов таблицы, а не в строках. Это делает тривиальным возврат данных в той форме, которую вы ищете, за счет того, чтобы быть немного больше работы, если правила изменятся.
Я много раз сталкивался с подобной проблемой . Я смотрю на это так: можете ли вы явным образом смоделировать книгу. Так, например, у вас есть 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 к n:
Таблица 1 со строками: ID Название Издатель и т. д.
Таблица 2 со строками: BookID Цена
«BookID» из таблицы 2 будет указывать на «ID» из таблицы 1, таким образом вы можете иметь столько цен, сколько захотите . Используйте JOIN (см. SQL-документацию), чтобы получить все цены на конкретную книгу.
Если вы предлагаете специальные скидки (например, при оптовой покупке 10% скидка, но 20% скидка, если клиент покупает более 100 товаров за раз), я бы предпочел рассчитать цену, а не хранить ее статически.
Это базовый вариант использования таблицы моста, в которой у вас есть:
1 таблица для информации о книге
1 таблица для информации о ценах
1 таблица-мост для объедините их вместе для каждого экземпляра книги и цены.
Думаю, у меня была аналогичная проблема.
Я решил эту проблему с помощью конструкции t-sql 'pivot'
(уродство: вы должны явно указать столбцы в запросе)
Мы используем T -SQL.
Я не знаю диалекта sql, который вы используете, поэтому он может быть неприменим.
Возможно, это может сделать то, что вы хотите.
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 и т. Д.
Изменить: извините за неправильное прочтение вопроса
Здесь вы можете использовать три таблицы для представления вашей модели, одну для книг:
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
Вопрос в следующем:
Будет ли список типов цен на книги статичным? Или типы цен (цена на День Колумба, специальная цена на Супербоул 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)
)