Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在此场景中使用交叉应用_Sql Server - Fatal编程技术网

Sql server 如何在此场景中使用交叉应用

Sql server 如何在此场景中使用交叉应用,sql-server,Sql Server,我有一个ProductStatus表,如下所示。我需要列出所有最新状态为“SU”的产品。除此之外,我还需要列出该产品以前的状态 基于对不同职位的介绍,交叉申请似乎适合这个职位。我做了如下所列的尝试,但没有得到预期的结果 在SQLServer2005中实现这一点而不使用子查询的最佳方法是什么 DECLARE @ProductStatus TABLE (ProductStatusID INT, productCode VARCHAR(5), statusCode VARCHAR(2)) INSE

我有一个ProductStatus表,如下所示。我需要列出所有最新状态为“SU”的产品。除此之外,我还需要列出该产品以前的状态

基于对不同职位的介绍,交叉申请似乎适合这个职位。我做了如下所列的尝试,但没有得到预期的结果

在SQLServer2005中实现这一点而不使用子查询的最佳方法是什么

DECLARE @ProductStatus TABLE (ProductStatusID INT,  productCode VARCHAR(5), statusCode VARCHAR(2))

INSERT INTO @ProductStatus

SELECT 1,'10011','RE'  --Recevied
UNION
SELECT 2,'10011','SU'  --Suspended

UNION
SELECT 3,'10012','IT'  -- In Transit
UNION
SELECT 4,'10012','RE' -- Received
UNION
SELECT 10,'10012','PR' -- Produced
UNION
SELECT 12,'10012','SU'  -- Suspended

UNION
SELECT 14,'10013','RE'  -- Recevied

UNION
SELECT 16,'10014','SU'  -- Recevied
UNION
SELECT 18,'10014','RE'  -- Recevied
交叉应用尝试

SELECT *
FROM @ProductStatus P
CROSS APPLY 
(
   SELECT MAX(V.ProductStatusID) as maxVal
   FROM @ProductStatus V
   WHERE V.ProductCode = P.ProductCode
   AND V. ProductStatusID <  P.ProductStatusID 
   GROUP BY V.ProductCode   
)ML
WHERE P.statusCode = 'SU'
预期结果


这是一个复杂的解决方案,主要用于说明这可能应该使用行数来完成:


Lijo,我把它组织成一个CTE,这样你就可以看到我是如何发展我的想法的。如果您对这些查询比较熟悉,那么可以将其重构为子查询而不影响其含义

;with MostRecentStatus as (
select
    MAX(ProductStatusID) as ProductStatusID,
    productCode
from @ProductStatus as p1
group by productCode
)
,MostRecentIsSU as (
select
    p2.ProductStatusID,
    p2.productCode,
    p2.statusCode
from MostRecentStatus as mrs
inner join @ProductStatus as p2
    on p2.ProductStatusID = mrs.ProductStatusID
    and p2.statusCode = 'SU'
)
select
    m.ProductStatusID,
    m.productCode,
    m.statusCode,
    p3.statusCode as PrevStatus,
    p3.ProductStatusID as PrevProductStatusID
from MostRecentIsSU as m
left outer join @ProductStatus as p3
    on p3.productCode = m.productcode
    and p3.ProductStatusID = m.ProductStatusID - 1;
编辑:…这是一个排号版本,对@attila表示敬意

;with InSquence as
(
    select
        ProductStatusID,
        productCode,
        statusCode,
        ROW_NUMBER() OVER(PARTITION BY productCode ORDER BY ProductStatusID desc) as Sequence
    from @ProductStatus
)
,FirstIsSU as
(
    select
        ProductStatusID,
        productCode
    from InSquence
    where Sequence = 1
    and statusCode = 'SU'
)
,PreviousCode as
(
    select
        ProductStatusID,
        productCode,
        statusCode
    from InSquence
    where Sequence = 2
)
select
    f.ProductStatusID,
    f.productCode,
    'SU' as CurrentStatus,
    p.statusCode as PrevStatus,
    p.ProductStatusID as PrevProductStatusID
from FirstIsSU as f
left outer join PreviousCode as p
    on p.productCode = f.ProductCode;
您可以通过交叉应用来实现这一点,但我认为行数是一种更简单的方法:

select ProductCode,
       max(case when seqnum = 1 then statusCode end) as LastStatus,
       max(case when seqnum = 2 then statusCode end) as PrevStatus
from (select p.*,
             row_number() over (partition by ProductCode order by ProductStatusId desc) as seqnum
      from @ProductStatus p
     ) p
group by ProductCode
having max(case when seqnum = 1 then statusCode end) = 'SU';

使用函数时通常需要交叉应用。我在这里看不到任何功能。当您希望为每一行的组合创建一个叉积时,可以使用交叉联接,在您的示例中,9x9=81行。我再次认为没有理由这样做。简言之,忘记交叉任何东西。@electricalma是的。ProductStatusID是用于查找上一个的列。关于。。。在productstatusid desc排序的产品id中添加一个行号窗口函数,然后选择行号=1和状态=SU的位置,加入行号=2和产品id。实际上我看到10014不应该出现在结果中,因为它最新的不是SU,而是RE。是吗?是的,结果中不应该有“10014”。你知道,进一步看数据,我的解决方案完全不正确!如果@Atilla没有给出答案,我将使用他的建议。我已经修改了我的答案,因此它确实产生了正确的结果,尽管没有使用我们无法依赖的行号和p3.ProductStatusID=m.ProductStatusID-1;中间可能有其他产品数据。。我已经用这个场景更新了这个问题
select ProductCode,
       max(case when seqnum = 1 then statusCode end) as LastStatus,
       max(case when seqnum = 2 then statusCode end) as PrevStatus
from (select p.*,
             row_number() over (partition by ProductCode order by ProductStatusId desc) as seqnum
      from @ProductStatus p
     ) p
group by ProductCode
having max(case when seqnum = 1 then statusCode end) = 'SU';