大家好,我已经传承了一个设计不佳的数据库,我需要从3个表中获取一些信息
特许
Id(Int, PK)
FrID (varchar(50))
FirstName (varchar(50))
LastName (varchar(50))
商品
Id (Int, PK)
FrID (varchar(50))
StoreNumber (varchar(50))
StoreName
Address
定价
Id (int, PK)
StoreNumber (varchar(50))
Price1
Price2
Price3
和数据
ID, FrID ,FirstName,LastName
1, 10 ,John Q , TestCase
2, 10 ,Jack Q , TestCase
3, 11 ,Jack Q , TestCase
ID, FrID, StoreNumber , StoreName , Address
10, 10 , 22222 , TestStore1, 123 Main street
11, 10 , 33333 , TestStore2, 144 Last Street
12, 10 , 44444 , TestStore2, 145 Next Street
13, 11 , 55555 , Other Test, 156 Other st
ID, StoreNumber, Price1, Price2, Price3
1, 22222 , 19.99, 20.99 , 30.99
2, 33333 , 19.99, 20.99 , 30.99
3, 44444 , 19.99, 20.99 , 30.99
4, 55555 , 19.99, 20.99 , 30.99
这就是我所做的
SELECT F.FirstName,F.LastName,F.FrID , S.StoreNumber,S.StoreName,S.Address,
P.Price1,P.Price2,P.Price3
FROM Franchisee F
JOIN Store S on F.FrID = S.FrID
JOIN Pricing P on P.StoreNumber = S.StoreNumber
这部分有效,但我最终得到了很多重复,例如Jack Q被列为他的商店以及John Q所在的每家商店。无论如何都要通过数据库重新设计来解决这个问题。
答案 0 :(得分:1)
好的,有一整套问题清单,例如[FrId]等字符字段用作字符串,[地址]等保留字用作名称等。
让我们把糟糕的设计问题放在一边。
首先,我需要创建一个快速测试环境。我没有输入外键,因为不需要该约束来获得正确的答案。
--
-- Setup test tables
--
-- Just playing
use Tempdb;
go
-- drop table
if object_id('franchise')> 0
drop table franchise;
go
-- create table
create table franchise
(
Id int primary key,
FrID varchar(50),
FirstName varchar(50),
LastName varchar(50)
);
-- insert data
insert into franchise values
( 1, 10, 'John Q', 'TestCase'),
( 2, 10, 'Jack Q', 'TestCase'),
( 3, 11, 'Jack Q', 'TestCase');
-- select data
select * from franchise;
go
-- drop table
if object_id('store')> 0
drop table store;
go
-- create table
create table store
(
Id int primary key,
FrID varchar(50),
StoreNumber varchar(50),
StoreName varchar(50),
Address varchar(50)
);
-- insert data
insert into store values
(10, 10, 22222, 'TestStore1', '123 Main street'),
(11, 10, 33333, 'TestStore2', '144 Last Street'),
(12, 10, 44444, 'TestStore2', '145 Next Street'),
(13, 11, 55555, 'Other Test', '156 Other Street');
-- select data
select * from store;
go
-- drop table
if object_id('pricing')> 0
drop table pricing;
go
-- create table
create table pricing
(
Id int primary key,
StoreNumber varchar(50),
Price1 money,
Price2 money,
Price3 money
);
-- insert data
insert into pricing values
(1, 22222, 19.99, 20.99 , 30.99),
(2, 33333, 19.99, 20.99 , 30.99),
(3, 44444, 19.99, 20.99 , 30.99),
(4, 55555, 19.95, 20.95 , 30.95);
-- select data
select * from pricing;
go
主要问题是特许经营权表应该在FrId上有主键(PK),而不是Id。我不明白为什么有重复。
但是,下面的查询会通过分组删除它们。我更改了Jack Q的定价数据,以显示它是一个不同的记录。
--
-- Fixed Query - Version 1
--
select
f.FirstName,
f.LastName,
f.FrID,
s.StoreNumber,
s.StoreName,
s.Address,
p.Price1,
p.Price2,
p.Price3
from
-- Remove duplicates from francise
(
select
LastName,
FirstName,
Max(FrID) as FrID
from
franchise
group by
LastName,
FirstName
) as f
join store s on f.FrID = s.FrID
join pricing p on p.StoreNumber = s.StoreNumber;
正确的输出如下。
如果我没错,请删除重复条目并更改主键。
更改要求
好的,您将两个或更多所有者放在同一张桌子中。
下面使用子查询将所有者列表合并为一个字符串。另一种方法是拥有一个名为主要所有者的标志。选择它作为显示名称。
--
-- Fixed Query - Version 2
--
select
f.OwnersList,
f.FrID,
s.StoreNumber,
s.StoreName,
s.Address,
p.Price1,
p.Price2,
p.Price3
from
-- Compose owners list
(
select
FrID,
(
SELECT FirstName + ' ' + LastName + ';'
FROM franchise as inner1
WHERE inner1.FrID = outer1.FrID
FOR XML PATH('')
) as OwnersList
from franchise as outer1
group by FrID
) as f (FrId, OwnersList)
join store s on f.FrID = s.FrID
join pricing p on p.StoreNumber = s.StoreNumber
以下是第二个查询的输出。