2014-10-14 3 views
4

어쩌면 나는 미쳐 버리거나 휴식을 취해야 할 것입니다. 그러나 내 레일 콘솔에서 Order.where(state: nil).count1010을 반환하지만 은 0을 반환합니다 ... 주문 상태가 nil이면 "대기 중"이 아니므로 세트는 not(state: "pending")에 의해 where(state: nil) 세트를 포함하도록 반환됩니다.은`where.not (field : "something")`include`where (field : nil)`이 아니어야합니다.

이런 식으로 작동하지 않습니까? 그렇지 않다면 다른 방식으로 작동합니까?

편집 : 더 많은 정보! 어떤 레코드가 nil이 아닌 다른 데이터베이스에 가서 실행할 때 Order.where.not(state: "pending").count 나는 여러개의 명령을 되돌려 놓았습니다. 아무 것도 "보류 중"이고 아무 것도 nil이 아닙니다. where.not이 암시 적으로 and not nil을 쿼리에 추가 한 것으로 보입니까?

편집 : 필사적으로, 나는 더 어두운 영혼으로 변했습니다.

# look into another shop, that has records 
o = Order.where(shop_id: 2) 

# summon dread spirits 
t = Order.arel_table[:state] 

o.where(t.eq(nil).or(t.eq("pending").not)).count 

=> 1569 

o.where(t.eq(nil)).count 

=> 1471 

그래서이 경우에는, 나는 그 상태 전무도 "보류"도 아닌 98 개 기록을 얻을, 나는 그 상태 전무 모든 기록을 얻을. 나는 단지 내가 왜 where.not("pending")라고 말할 수없고 같은 효과가 있는지를 알고 싶다. 내가 호출 할 수있는 옵션이 있다면? 좋아, where.not("pending", include_nil: true)?

편집 : @Filip Bartuzi에 의해 코멘트에 요청에 따라

Order.where.not(state: "pending").to_sql 

=> "SELECT \"orders\".* FROM \"orders\" WHERE \"orders\".\"shop_id\" = 2 AND (\"orders\".\"state\" != 'pending')" 

Orders.where(state: nil).to_sql 

=> "SELECT \"orders\".* FROM \"orders\" WHERE \"orders\".\"shop_id\" = 2 AND \"orders\".\"state\" IS NULL" 
+0

데이터베이스에'NULL' /' 'pending'' 값만 있습니까? 'Order.pluck (: state)' –

+0

불행히도 나는 레일스 환경에 접근 할 수 없기 때문에 스스로 테스트 할 수는 없지만'Order.where.not (status : "보류 중"). to_sql' 및 Order.where (상태 : nil) –

+0

너무 영리합니다! – Ziggy

답변

5

Order.where.not(state: "pending").to_sql를 생성 :

=> "SELECT \"orders\".* FROM \"orders\" WHERE \"orders\".\"shop_id\" = 2 AND (\"orders\".\"state\" != 'pending')"

그것은 '보류'하지 않는 값으로 모든 레코드를 반환합니다. .이 SELECT 응답

에 포함되지 않도록 유 (Order.first.update! state: nil를 같은이 데이터베이스에 NULL 할당

NULL SQL에서 값으로 해석되지 nilpending을 설정하면 그래서 대답은 : where.not(field: “something”)은 포함되지 않습니다 ! where(field: nil)

가 여기에 어떻게 작동하는지 확인할 수 있습니다

http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all

범주 테이블로 이동하여 먼저 이제 우리가 그들 중 하나가 열 CategoryName

NULL을 가지고 카운트 8의 카테고리를

UPDATE Categories 
SET CategoryName = NULL 
WHERE CategoryName = 'Beverages' 

을 실행 지금 실행 : 당신으로

SELECT CategoryName FROM Categories 
WHERE CategoryName != 'Condiments' 

반환 된 레코드 6 개 참조 (따라서 NULL으로 건너 뜁니다)

+0

OK, 그래서 값이 아닌 것이 아닌 값을 모두 포함하려면 항상 arel_table 스타일'또는'쿼리로 이동해야합니까? 아니면 다른 방법이 있습니까? – Ziggy

+0

첫째로 나는 어떤 값도 NULL로 나타내지 말아야한다고 생각한다. 따라서 주문이 '보류 중'또는 '취소 중'일 수있는 경우 '취소'를 문자열 또는 숫자로 저장해야합니다. Rails 4를 사용한다면 주문 모델 –

+0

에'enum'을 사용하는 것이 좋습니다. nil을 기본 상태로 사용하고 있었지만 기본 상태가 실제 상태 여야한다는 것이 맞습니다. 좋은 조언. – Ziggy

2

SQL 구현은 NULL이 값이 아니지만 값이 없다는 3 가지 논리를 따릅니다.3 값 논리는 논리 연산에 대해 다음 진리표를 정의 진리표에 의해 데이터 세트의 각 항목에 항등 (row.state == 'pending') 용

p  |q  |p OR q |p AND q|p = q 
True |True |True |True |True 
True |False |True |False |False 
True |Unknow |True |Unknown|Unknown 
False |True |True |False |False 
False |False |False |False |True 
False |Unknown|Unknown|False |Unknown 
Unknown |True |True |Unknown|Unknown 
Unknown |False |Unknown|False |Unknown 
Unknown |Unknown|Unknown|Unknown|Unknown 

where 이후 시험 row.state 경우 상기 (널 여기서 알 수있다) NULL 인 경우 결과는 '알 수 없음'입니다. '알 수 없음'은 true가 아니므로 행이 결과 집합에 포함되지 않습니다.

자세한 정보는 Wikipedia입니다.