如何获得特定订单

时间:2014-02-24 15:21:32

标签: sql sql-server

我有这个数据表,可以对下一张图片中的信息进行编码。

 +----+----------------------------+------+-------+-----------+--------+-------+
| ID |          Element           | Type | LEVEL | ElemOrder | Header | Total |
+----+----------------------------+------+-------+-----------+--------+-------+
|  1 | IncomeStatement            | H    |     1 |         0 | NULL   | NULL  |
|  2 | OperatingIncome            | H    |     2 |         0 | 1      | NULL  |
|  3 | OtherIncome                | H    |     2 |         1 | 1      | NULL  |
|  4 | EarningsBeforeInterestTax  | R    |     2 |         3 | 1      | NULL  |
|  5 | InterestExpense            | R    |     2 |         4 | 1      | NULL  |
|  6 | NetProfitBeforeTax         | R    |     2 |         5 | 1      | NULL  |
|  7 | TaxExpenses                | R    |     2 |         6 | 1      | NULL  |
|  8 | NetProfitAfterTax          | R    |     2 |         7 | 1      | NULL  |
|  9 | DividendPaidShareholders   | R    |     2 |         8 | 1      | NULL  |
| 10 | RetainedEarnings           | R    |     2 |         9 | 1      | NULL  |
| 11 | GrossProfit                | H    |     3 |         0 | 2      | NULL  |
| 12 | OperatingExpense           | H    |     3 |         1 | 2      | NULL  |
| 13 | Revenue                    | R    |     4 |         0 | 11     | NULL  |
| 14 | CostSales                  | R    |     4 |         1 | 11     | NULL  |
| 15 | GrossProfitTotal           | R    |     4 |         2 | 11     | NULL  |
| 16 | SalesMarketingCosts        | R    |     4 |         0 | 12     | NULL  |
| 17 | GeneralAdministrationCosts | R    |     4 |         1 | 12     | NULL  |
| 18 | ResearchDevelopmentCosts   | R    |     4 |         2 | 12     | NULL  |
| 19 | OperatingExpensesTotal     | R    |     4 |         3 | 12     | NULL  |
| 20 | HeaderTotal 11             | T    |     3 |      1000 | NULL   | 11    |
| 21 | HeaderTotal 12             | T    |     3 |      1000 | NULL   | 12    |
| 22 | HeaderTotal 2              | T    |     2 |      1000 | NULL   | 2     |
| 23 | HeaderTotal 3              | T    |     2 |      1000 | NULL   | 3     |
| 24 | HeaderTotal 1              | T    |     1 |      1000 | NULL   | 1     |
+----+----------------------------+------+-------+-----------+--------+-------+

enter image description here

元素类型HR的行是图像中的行。 T类型的行稍后已添加。

这个结构实际上是一个所有LEAFS都为R的树 - 类型和其他节点,它们是父节点H - 类型。

每个H - 类型节点应该有一个对应的T类型节点,并且最后会添加这些节点。

EXPECTED OUTPUT:

我的问题是我试图按以下顺序获取所有元素(它们在图像中显示的方式,从上到下,但每个H线必须由T线关闭):

+----+-------------------------------+------+-------+-------+--------+-------+
| ID |             Name              | Type | Level | Order | Header | Total |
+----+-------------------------------+------+-------+-------+--------+-------+
|  1 | Income Statement              | H    |     1 |     1 | NULL   | NULL  |
|  2 | Operating Income              | H    |     2 |     1 | 1      | NULL  |
| 11 | Gross Profit                  | H    |     3 |     1 | 2      | NULL  |
| 13 | Revenue                       | R    |     4 |     1 | 11     | NULL  |
| 14 | CostSales                     | R    |     4 |     2 | 11     | NULL  |
| 15 | CostThirdParties              | R    |     4 |     3 | 11     | NULL  |
| 16 | GrossProfitTotal              | R    |     4 |     4 | 11     | NULL  |
| 28 | Gross Profit TOTAL NODE       | T    |     3 |     2 | NULL   | 11    |
| 12 | Operating Expenses            | H    |     3 |     3 | 2      | NULL  |
| 17 | SalesMarketingCosts           | R    |     4 |     1 | 12     | NULL  |
| 18 | GeneralAdministrationCosts    | R    |     4 |     2 | 12     | NULL  |
| 19 | ResearchDevelopmentCosts      | R    |     4 |     3 | 12     | NULL  |
| 20 | OperatingExpensesTotal        | R    |     4 |     4 | 12     | NULL  |
| 27 | Operating Expenses TOTAL NODE | T    |     3 |     4 | NULL   | 12    |
| 26 | Operating Income TOTAL NODE   | T    |     2 |     2 | NULL   | 2     |
|  3 | Other Income                  | H    |     2 |     3 | 1      | NULL  |
| 21 | InterestIncome                | R    |     3 |     1 | 3      | NULL  |
| 22 | DividendIncome                | R    |     3 |     2 | 3      | NULL  |
| 23 | OtherIncomeTotal              | R    |     3 |     3 | 3      | NULL  |
| 25 | Other Income TOTAL NODE       | T    |     2 |     4 | NULL   | 3     |
|  4 | EarningsBeforeInterestTax     | R    |     2 |     5 | 1      | NULL  |
|  5 | InterestExpenses              | R    |     2 |     6 | 1      | NULL  |
|  6 | NetProfitBeforeTax            | R    |     2 |     7 | 1      | NULL  |
|  7 | TaxExpenses                   | R    |     2 |     8 | 1      | NULL  |
|  8 | NetProfitAfterTax             | R    |     2 |     9 | 1      | NULL  |
|  9 | DividendPaidShareholders      | R    |     2 |    10 | 1      | NULL  |
| 10 | RetainedEarnings              | R    |     2 |    11 | 1      | NULL  |
| 24 | Income Statement TOTAL NODE   | T    |     1 |     2 | NULL   | 1     |
+----+-------------------------------+------+-------+-------+--------+-------+

我只想简单地按ORDER BY特定列,但我似乎无法找到方法。我不确定,但我有一种感觉,我必须以递归的方式遍历表格,以便将TOTAL行放在应该位于的位置。

我的查询很简单,不是重点,我正在努力找到正确的顺序。

SELECT
    ID,
    Element,
    Type,
    LEVEL,
    ElemOrder,
    Header,
    Total
FROM myTable

2 个答案:

答案 0 :(得分:2)

这是类型字段的基本排序,您可以添加其他排序条件

试试这个:

SELECT
  ID,
  Element,
  Type,
  LEVEL,
  ElemOrder,
  Header,
  Total
FROM myTable
ORDER BY
CASE 
  when type = 'H' then 1
  when type = 'R' then 2
  when type = 'T' then 3
end

答案 1 :(得分:2)

如果没有先到树的每个节点,就无法生成层次排序。这是因为表的树/行的每个节点仅包含有关其自身及其直接父节点的信息;如果没有完整的“地址”描述行在最终报告中的位置,则无法应用排序。

幸运的是,我们可以使用ASCII字符串的排序方式,使用基于集合的逻辑快速生成地址。递归是没有必要的;我们所要做的就是:

  1. 查找树的根(在此特定情况下,不带父项的标题行(HEADER is NULL)并构建根的地址。

  2. 查找具有父地址值的所有节点,并将父地址复制到子节点,附加有关子节点的其他信息

  3. 重复步骤2,直到所有节点都填充了一个地址。

  4. 在您的具体情况下,我通过将上述内容仅应用于标题行来简化操作;叶子和总数在单独的陈述中更新。

    这将在SQL Server 2008中运行。

    CREATE TABLE mytable
        ([ID] int, [Element] varchar(26), [Type] varchar(1), [LEVEL] int, [ElemOrder] int, [Header] varchar(4), [Total] varchar(4))
    ;
    
    INSERT INTO mytable
        ([ID], [Element], [Type], [LEVEL], [ElemOrder], [Header], [Total])
    VALUES
        (1, 'IncomeStatement', 'H', 1, 0, NULL, NULL),
        (2, 'OperatingIncome', 'H', 2, 0, '1', NULL),
        (3, 'OtherIncome', 'H', 2, 1, '1', NULL),
        (4, 'EarningsBeforeInterestTax', 'R', 2, 3, '1', NULL),
        (5, 'InterestExpense', 'R', 2, 4, '1', NULL),
        (6, 'NetProfitBeforeTax', 'R', 2, 5, '1', NULL),
        (7, 'TaxExpenses', 'R', 2, 6, '1', NULL),
        (8, 'NetProfitAfterTax', 'R', 2, 7, '1', NULL),
        (9, 'DividendPaidShareholders', 'R', 2, 8, '1', NULL),
        (10, 'RetainedEarnings', 'R', 2, 9, '1', NULL),
        (11, 'GrossProfit', 'H', 3, 0, '2', NULL),
        (12, 'OperatingExpense', 'H', 3, 1, '2', NULL),
        (13, 'Revenue', 'R', 4, 0, '11', NULL),
        (14, 'CostSales', 'R', 4, 1, '11', NULL),
        (15, 'GrossProfitTotal', 'R', 4, 2, '11', NULL),
        (16, 'SalesMarketingCosts', 'R', 4, 0, '12', NULL),
        (17, 'GeneralAdministrationCosts', 'R', 4, 1, '12', NULL),
        (18, 'ResearchDevelopmentCosts', 'R', 4, 2, '12', NULL),
        (19, 'OperatingExpensesTotal', 'R', 4, 3, '12', NULL),
        (20, 'HeaderTotal 11', 'T', 3, 1000, NULL, '11'),
        (21, 'HeaderTotal 12', 'T', 3, 1000, NULL, '12'),
        (22, 'HeaderTotal 2', 'T', 2, 1000, NULL, '2'),
        (23, 'HeaderTotal 3', 'T', 2, 1000, NULL, '3'),
        (24, 'HeaderTotal 1', 'T', 1, 1000, NULL, '1')
    ;
    
    
    
    
    declare @sorttable table (id bigint, sort_order varchar(max) )
    
    insert into @sorttable (id)
    select id from mytable
    
    
    update @sorttable
    set sort_order = RIGHT('000000' + CONVERT (varchar(max), id),6)+'.'
    where id in (select id from mytable where Header is null and Type = 'h')
    
    
    while exists (select * from mytable mt
                    inner join @sorttable st on mt.ID = st.id where st.sort_order is null and mt.Type = 'H')
    BEGIN
    
    update @sorttable
    set sort_order = q.sort_order + RIGHT('000000' + CONVERT (varchar(max), q.child_id),6) +'.'
    from 
    (
        select par_st.sort_order, mt_child.ID as child_id from mytable mt_par
        inner join mytable mt_child on mt_child.Header = mt_par.ID
        inner join @sorttable par_st on mt_par.ID = par_st.id
    ) q
    
    where q.child_id = id and id in (select id from mytable where Type = 'H')
    
    END
    
    update @sorttable
    set sort_order = q.sort_order + RIGHT('000000' + CONVERT (varchar(max), q.child_id),6)
    from 
    (
        select par_st.sort_order, mt_child.ElemOrder as finalorder, mt_child.ID as child_id from mytable mt_par
        inner join mytable mt_child on mt_child.Header = mt_par.ID
        inner join @sorttable par_st on mt_par.ID = par_st.id
    ) q
    
    where q.child_id = id and id in (select id from mytable where Type ='R')
    
    
    update @sorttable
    set sort_order = q.sort_order + '999999'
    from 
    (
        select par_st.sort_order, mt_child.ElemOrder as finalorder, mt_child.ID as child_id from mytable mt_par
        inner join mytable mt_child on mt_child.Total = mt_par.ID
        inner join @sorttable par_st on mt_par.ID = par_st.id
    ) q
    where q.child_id = id and id in (select id from mytable where Type = 'T')
    
    select * from mytable mt
    inner join @sorttable st on mt.ID = st.id
    order by sort_order 
    

    SQLFiddle of solution in operation.