2009-05-11 43 views
11

Tôi đang cố gắng trích xuất số tiền được lưu trữ trong một số cột xml được định dạng kém (không có lược đồ nào được xác định cho cột XML mà tôi đoán là một phần của vấn đề). Tôi nhận được một lỗi chuyển đổi bất cứ khi nào tôi gặp phải một nút với 0 là giá trị của nó.XQuery trong SQL server làm SUM trên 0 giá trị

Ví dụ:

select xml.value('sum(/List/value)', 'numeric') sum 
from (select cast('<List><value>1</value><value>2</value></List>' as xml) xml) a 

cho tổng 3 khi:

select xml.value('sum(/List/value)', 'numeric') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

làm tăng lỗi: "Lỗi chuyển đổi kiểu dữ liệu nvarchar sang số"

Bất kỳ ý tưởng nào làm cách nào để truy vấn của tôi trả về 0 khi tổng hợp danh sách các nút không có giá trị?

+3

Dường như tổng (/ Danh sách/giá trị) trả về một dấu phẩy "0.0E0" khi tổng là bằng không và số đó không thể được chuyển thành số. Bất kỳ ý tưởng tại sao tôi thấy hành vi này? –

Trả lời

6

Nhận xét của bạn cho thấy câu trả lời cho vấn đề của bạn.

Thay vì chuyển đổi thành số, chuyển đổi thành nổi. Ký pháp khoa học sẽ chuyển thành phao.

3

bạn cũng có thể sử dụng và nếu tuyên bố như thế này:

@x.value('if (sum(/List/value) = 0) then 0 else sum(/List/value)', 'numeric') 
3

tôi stumbled trên câu hỏi này, và cuối cùng là một câu trả lời, khi nhìn vào một vấn đề tương tự với số nguyên. Mặc dù sự chậm trễ kể từ câu trả lời cuối cùng, tôi đang thêm vào đây trong trường hợp nó giúp bất cứ ai khác trong tương lai.

Trước câu trả lời cơ bản của bạn:

select xml.value('xs:decimal(sum(/List/value))', 'numeric') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

Trong XQuery bạn có thể đúc các giá trị cho một loại Schema XML tiêu chuẩn, sau đó sẽ được xử lý một cách chính xác bởi SQL Server.

XIN LƯU Ý: mặc định "số" trong SQL Server không có bất kỳ vị trí thập phân nào (tỷ lệ "0")! Bạn có thể dùng để làm một cái gì đó giống như hơn:

select xml.value('xs:decimal(sum(/List/value))', 'numeric(20,5))') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

(bạn không thể có được SQL Server để suy ra độ chính xác hoặc quy mô từ giá trị trả về từ Xml, bạn phải xác định nó một cách rõ ràng)

Cuối cùng, thực tế vấn đề mà cá nhân tôi cần thiết để địa chỉ là gần như giống hệt nhau, ngoại trừ tôi đã đối phó với số nguyên, mà cũng phải vật lộn với các đại diện xml "0" double giá trị:

select xml.value('xs:int(sum(/List/value))', 'int') sum 
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a 

UPDATE: Vấn đề với giải pháp xử lý số thập phân mà tôi đã đăng ở trên (chuyển đổi sang thập phân trong XQuery trước khi SQL phân tích giá trị) là kết hợp thực sự xảy ra với loại dữ liệu dấu chấm động (kép). Nếu các giá trị bạn đã lưu trữ trong Xml của bạn yêu cầu mức độ chính xác cao, điều này thực sự có thể là điều sai phải làm - tập hợp dấu phẩy động thực sự có thể dẫn đến mất dữ liệu. EG đây chúng ta mất đi chữ số cuối cùng của số chúng ta đang tổng hợp:

select xml.value('xs:decimal(sum(/List/value))', 'numeric(28, 0)') sum 
from (select cast('<List> 
     <value>1000000000000000000000000001</value> 
     <value>1000000000000000000000000001</value> 
    </List>' as xml) xml) a 

(đi ra để "2000000000000000000000000000", đó là sai)

Vấn đề này đều áp dụng phương pháp tiếp cận khác được cung cấp ở đây, chẳng hạn như một cách rõ ràng đọc giá trị là "phao" trong T-SQL.

Để tránh điều này, đây là tùy chọn cuối cùng sử dụng biểu thức XQuery FLWOR để đặt kiểu dữ liệu trước hoạt động tổng hợp. Trong trường hợp này, tập hợp xảy ra một cách chính xác, và chúng tôi có giá trị tóm tắt chính xác (đồng thời cũng xử lý "0" giá trị nếu/khi chúng xảy ra):

select xml.value('sum(for $r in /List/value return xs:decimal($r))', 'numeric(28, 0)') sum 
from (select cast('<List> 
     <value>1000000000000000000000000001</value> 
     <value>1000000000000000000000000001</value> 
    </List>' as xml) xml) a 

(đi ra để "2000000000000000000000000002", giá trị đúng)

+0

Tôi thích phương pháp ở đây sử dụng XQuery để truyền giá trị cho một loại lược đồ XML tiêu chuẩn. Đó là chính xác những gì tôi đang tìm kiếm, và thích điều đó hơn là chuyển đổi nó thành một phao, và sau đó trở lại cái gì khác. Đó là một chút rõ ràng hơn, nhưng tôi có thể tránh di chuyển nó đến một loại và sau đó khác, và tôi nghĩ rằng đó là rõ ràng hơn. – mttjohnson

Các vấn đề liên quan