2010-12-13 2 views
1

나는이 방법 (I이 qeustions에 대한 일부 필드, 사람보고) 설계 간단한 customers 테이블이 : 널 (null)와SQL : 선박/송장 주소와 SELECT CONCAT 문제에 대한 테이블 디자인

+ ----------- + --------------- + ---------------- + 
+ 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는 운송을 위해 고객의 인보이스 주소를 사용해야 함을 의미합니다.


첫번째 질문 :이 충분히 좋은 디자인, 또는 모든 nullship_address 필드는 null 왼쪽 송장 주소 (심지어 동일한 경우) 및하지로 가득해야합니다.

두번째 질문 : 같은 디자인을 유지 (심지어 경우에 그것의 나쁜 디자인), (가능하다면) 내가 각 행에 대해 항상 하나의 주소를 반환하는 SELECT 쿼리를 만들려면 어떻게해야합니까 방법 : ship_address하지 null, 그렇지 않으면 단지 invoice_address, 같은 : MySQL의 DB에 대한

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

쿼리.

감사합니다.

답변

2

당신은 고객과 주소 사이에 1 대 다수의 관계를, 그래서 그들을 구별 할 수있는 "유형"을 별도의 테이블로 밖으로 해결 당겨 것 . 나는 주소 자체를 분리 된 속성으로 분리하는 것을 고려할 것이다. 선택적으로 유효한시 /도/국가에 대한 참조 테이블을 추가 할 수도 있습니다. 항상 존재하고 원하는 순서 인 AddressType 레코드를 생성 한 주소를 가정이 구조의 데이터를 쿼리로

alt text

(즉, 송장 = 1, 배송 = 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 
+0

이것들은 실제로 정말 독특한 곳을 배우게 해주는 답 유형입니다. 이 디자인은 훌륭합니다. 유일한 부작용은 고객 (주소 포함)에 대한 간단한 SELECT가 항상 JOIN이 필요하다는 것입니다. 그러나 Prodcution과 DB가 거대해질 수 있기를 기대하는 것은 확실히 올바른 길입니다. –

+0

사실 고객 - 주소가 n : m 관계이기 때문에 같은 주소가 둘 이상의 고객에게 동일 할 수 있습니다 (즉, 같은 회사의 다른 직원, 나는 선박 주소와 동일한 회사 주소를 사용합니다). 그러나 고객 주소록에서 CustomerAddressXref 테이블도 이것을 처리 할 수 ​​있습니다. BTW : 저는시, 주, .. fileds를 이미 분할 했었습니다. 간단하게 유지하기 위해 질문에 쓰지 않았습니다. –

+0

고객이 주소를 변경하면 어떻게됩니까? 고객의 이전 인보이스 주소는 역사적인 목적으로 변경되어서는 안됩니다. 그 때해야 할 일은 무엇입니까? – greaterKing

2

저는 스키마가 괜찮다고 생각합니다. 당신이 MS의 SQL 서버를 사용하는 경우이 같은 유착을 사용할 수 있습니다

select coalesce(ship_address,invoice_address) as address 
from customers 

유착은 기본적으로 항목의 목록을 소요하고, null가 아닌 목록의 첫 번째 항목을 표시합니다.

+1

이것은 매력처럼 작동합니다! COALESE는 MySQL에도 있습니다. –

+0

귀하의 답변은 제 질문과 작품에 잘 어울립니다, +1. 저는 Joe Stefanelli의 대답을 선택합니다. 왜냐하면 그것은 너무 효과적이기 때문에 더 완벽하고 제 1의 질문에도 잘 대답하기 때문입니다. –

1

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

이 답변은 완전히 잘못되었습니다. –

+0

오, MySQL에서 쿼리를 찾고 계십니까? 나는 처음에 MySQL 태그를 보았는데 MS SQl에 대한 것이라고 생각했다 .Im MS SQL ISNULL 함수는 expression 값 (왼쪽에있는 vaule)이 NULL 인 경우 대체 값을 설정하는 데 사용된다. 즉 ship_address가 null 인 경우 invoice_address의 값을 반환합니다.그리고 MySQL ISNULL 함수에서 NULL 값을 확인하는 것입니다, 맞습니까? – wizzardz

1

당신은 중복으로 이어질 것입니다 청구서 주소를 복사 null로 선박 주소를 남겨 두어야 할 것입니다. 쿼리로

:

SELECT invoice_address 
from table 
where ship_address IS Null 

UNION 

SELECT ship_address 
from table 
where ship_address IS NOT NULL 
+0

ship_address가 null 인 경우 정확히 'ISNULL'인 인보이스 – Programmer

+0

을 읽으십시오. – wizzardz