如何用其他机制替换SQL Server游标

时间:2019-04-17 16:04:07

标签: json sql-server

我正在使用SQL Server2008。我必须从两个具有一对多关系的表中创建json。这些表是CustomerOrders

每个客户可能有一个或多个订单。通过首先从客户表中获取数据,然后附加他们已进行的所有购买来构造json。

以下是我的查询。我还附上了查询的json输出。它可以工作并创建有效的json。问题是它太慢了,因为我使用游标在Customer表中循环。我已设法避免使用游标通过XML路径从Orders表中获取数据。由于必须处理数百万行,因此必须用其他某种机制来替换光标。

DECLARE @PaymentType VARCHAR(50),
        @Email VARCHAR(100), 
        @OrderId INT

DECLARE CustomerCursor CURSOR FAST_FORWARD FOR
    SELECT TOP 10 
        PaymentType, Email, OrderId 
    FROM 
        CUSTOMER

OPEN CustomerCursor

FETCH NEXT FROM CustomerCursor INTO @PaymentType, @Email, @OrderId

WHILE (@@FETCH_STATUS = 0)
BEGIN
    DECLARE @customer VARCHAR(MAX)
    DECLARE @order VARCHAR(MAX)
    DECLARE @customer_with_order VARCHAR(MAX)

    -- construct order json
    SET @order =  '[' + STUFF((SELECT ',{"orderProductID":' + CAST(orderProductID AS VARCHAR) + 
                                      ',"productType":"' + ProductType + '"' + 
                                      ',"productName":"' + ProductName + '"' +
                                      ',"categoryName":"' + CategoryName + '"' + '}'
                               FROM ORDERS 
                               WHERE orderid = @OrderId
                               FOR XML PAT(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '') + ']'
    -- construct customer json
    SET @customer = '{"email":"' + CASE WHEN @Email IS NULL THEN '' ELSE 
   @Email END + '"'
                + ',"eventName": "ChristmasSale", "dataFields": {' 
                + '"orderId":' + CAST(CASE WHEN @OrderId IS NULL THEN 0 ELSE 
    @OrderId  END AS VARCHAR)                   
                + ',"paymentType":"' + CASE WHEN @PaymentType IS NULL THEN 
    '' ELSE @PaymentType END + '"'                  
                + ',"products": '

    -- combine these two
    SET @customer_with_order = @customer + @order + '}}'

    -- insert into CUSTOMER_ORDER_DATA
    INSERT INTO CUSTOMER_ORDER_DATA(email, order_id, orders) 
    VALUES (@Email, @OrderId, @customer_with_order)

    FETCH NEXT FROM CustomerCursor INTO @PaymentType, @Email, @OrderId
END

CLOSE CustomerCursor
DEALLOCATE CustomerCursor

enter image description here

1 个答案:

答案 0 :(得分:2)

我无法对此进行测试,但我怀疑您可以将以下内容重写为基于的基于集合的方法(由于我无法进行测试,因此无法确定是否可以使用,如果没有,则可能需要对其进行一些故障排除)

from bs4 import BeautifulSoup as bs
s = {"error":0,"msg":"<font color=blue><b>Live</b></font><font color=green>Jumpman#23</font> | [MD5 Decrypt] .S/C0D3"}
soup = bs(s['msg'], 'lxml')
data =  soup.select_one('font + font').text
print(data)

考虑到OP具有500万行,那么对于一批来说,这可能会有点多。将其分成大约10,000个批次可能对整体性能更好。不幸的是,OP仍在使用2008,因此他们无权访问<?php $filter = isset($_GET['sort']) ? $_GET['sort'] : false; $popNum = 5; // minimum amount of occurences to be considered 'popular' # prepare query $query = "SELECT * FROM `table_name`"; switch ($filter) { case 'pop': $query = "SELECT item, item_price item_description COUNT(*) FROM `table_name` GROUP BY item HAVING COUNT(*) > '$popNum' ORDER BY COUNT(*) DESC"; // most popular on top break; case 'lh': $query .= " ORDER BY item_price ASC"; // low to high break; case 'hl': $query .= " ORDER BY item_price DESC"; // high to low break; } // echo $query; // toggle to debug ?> <form action="<?=$_SERVER['REQUEST_URI'];?>" method="GET"> <select name="sort" id="myselect" onchange="this.form.submit()"> <option value="pop"<?=$filter == 'pop' ? ' selected' : false ?>>Sort by Popularity</option> <option value="lh"<?=$filter == 'lh' ? ' selected' : false ?>>Sort Low - High</option> <option value="hl"<?=$filter == 'hl' ? ' selected' : false ?>>Sort by High - Low</option> </select> <button onclick="window.location.replace('/index.php');">Reset</button> </form> 子句。