SQL: дизайн таблицы для адреса отправителя / счета и проблемы SELECT CONCAT - PullRequest
1 голос
/ 13 декабря 2010

У меня есть простая таблица customers, разработанная таким образом (я сообщаю только о некоторых полях, относящихся к данному вопросу):

+ ----------- + --------------- + ---------------- +
+ customer_id + invoice_address + ship_address     +
+ ----------- + --------------- + ---------------- +
+ 33          + 234, Walnut Ave + null             +
+ ----------- + --------------- + ---------------- +
+ 47          + 66, Smart Ave   + null             +
+ ----------- + --------------- + ---------------- +
+ 47          + 4, Cool Ave     + 45, Dark Street  +
+ ----------- + --------------- + ---------------- +

Строки с нулевым ship_address означает, что мы должны использовать счет клиентаадрес также для доставки.


1-й вопрос: это достаточно хороший дизайн, или все поля null ship_address должны быть заполнены адресом счета(даже если они идентичны) и не осталось null.

2-й вопрос: Сохраняя такой дизайн (даже в случае, если он плохой), как мне создать запрос SELECT (если онвозможно), который всегда возвращает один отдельный адрес для каждой строки: ship_address, когда НЕ null, в противном случае просто invoice_address, что-то вроде:

SELECT CONCAT_IF_SHIP_ADDRESS_NOT_NULL_OTHERWISE_USE_ONLY_SHIP_ADDRESS(invoice_address, ship_address) AS address FROM customers;

Запрос для БД MySQL.

Спасибо

Ответы [ 4 ]

2 голосов
/ 13 декабря 2010

У вас есть отношение «один ко многим» между клиентами и адресами, поэтому я бы выделил адрес в отдельную таблицу с «типом», чтобы различать их. Я бы подумал разбить сам адрес на отдельные атрибуты. При желании вы можете даже добавить справочные таблицы для действительных городов / штатов / стран.

alt text

Что касается запроса данных в этой структуре, при условии, что всегда существует 1 адрес, и вы создаете записи AddressType в желаемом порядке (т. Е. Invoice = 1, Shipping = 2):

select c.CustomerID, a.AddressLine1, a.AddressLine2, a.AddressLine3,
       a.City, a.State, a.PostalCode, a.Country
    from Customer c
        inner join (select MIN(cax.AddressTypeID) as MinAddressTypeID
                        from CustomerAddressXref cax
                        where cax.CustomerID = c.CustomerID
                        group by cax.CustomerID) mincax
        inner join CustomerAddressXref cax
            on c.CustomerID = cax.CustomerID
                and mincax.MinAddressTypeID = cax.AddressTypeID
        inner join Address a
            on cax.AddressID = a.AddressID
2 голосов
/ 13 декабря 2010

Я думаю, что схема в порядке. если вы используете сервер ms sql, вы можете использовать coalesce, например:

select coalesce(ship_address,invoice_address) as address 
from customers

coalesce в основном берет список элементов и отображает первый элемент в списке, который не равен нулю.

1 голос
/ 13 декабря 2010

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

Что касается запроса:

SELECT invoice_address
from table 
where ship_address IS Null

UNION

SELECT ship_address 
from table 
where ship_address IS NOT NULL
1 голос
/ 13 декабря 2010

Это будет делать

SELECT customer_id, ISNULL(ship_address,invoice_address) AS address
FROM customers
...