如何在SQL Server 2014中获得来自同一表的比较记录?

时间:2021-08-30 22:13:29

I have a table that shows the entry and exit of items into the warehouse. The Camera 1 and Camera 2 document the entry time and exit time respectively of that item. The cameras then classify the item as it enters and leaves the checkpoint with the help of lasers. Eg: Big box: Class 5, Medium Box: Class 3, Small Box: Class 2.

我有一个表,显示物品进入仓库的入口和出口。相机1和相机2分别记录该项目的进入时间和退出时间。在激光的帮助下,摄像机对进入和离开检查点的物品进行分类。大箱子:5班,中箱:3班,小箱子:2班。

Sometimes, the cameras classification doesn't match each other. Eg: Classification at entry can be Medium box and on exit can be Small box.

有时,相机的分类并不匹配。入口分类可以是中盒,出口分类可以是小盒。

I need to find the number of transactions where the class didn't match for the same TransactionDetail and then a percentage of those class mismatches against all the transaction for a certain time range.

我需要找到类不匹配相同事务细节的事务的数量,然后在一定的时间范围内,这些类的百分比不匹配所有事务。

My table looks somewhat like this:

我的桌子看起来有点像这样:

---------------------------------------------------------------------------
| AVDetailID | TransDetailID | AVClassID | CamID | CreatedDate            |
---------------------------------------------------------------------------
| 20101522   | 54125478      | 5         | 1     | 2017-05-08 10:15:01:560|
| 20101523   | 54125478      | 5         | 2     | 2017-05-08 10:15:01:620|
| 20101524   | 54125479      | 3         | 1     | 2017-05-08 10:15:03:120|
| 20101525   | 54125479      | 2         | 2     | 2017-05-08 10:15:03:860|
| 20101526   | 54125480      | 4         | 1     | 2017-05-08 10:15:06:330|
| 20101527   | 54125480      | 4         | 2     | 2017-05-08 10:15:06:850|
---------------------------------------------------------------------------

So, in the above case the class changes from 3 to 2 in record 3 and 4. That is one transaction where the class changed. I need to get a percentage of all transactions that where the class changed between each cameras.

在上面的例子中,类在记录3和4中从3变为2。这是一个类更改的事务。我需要得到所有事务的百分比在每个摄像机之间类的变化。

The code I've used so far is below. I just need to find a way to get a percentage of the total Transactions.

我到目前为止使用的代码在下面。我只需要找到一种方法来获得总交易的百分比。

DECLARE @MinDate DATE = '20170406',
        @MaxDate DATE = '20170407';

SELECT  COUNT(tdBefore.TransDetailId) TD
        --,SUM((COUNT(*) OVER() / allRecords.Count) * 100) AS DiffPercent

FROM    AVTransDetail AS tdBefore
INNER JOIN AVTransDetail AS tdAfter
    ON tdBefore.TransDetailID = tdAfter.TransDetailID 
    AND tdBefore.ACClassID = 1
    AND tdAfter.ACClassID = 2
CROSS APPLY
(
    SELECT COUNT(*) AS [Count]
    FROM AVTransDetail
    WHERE tdBefore.DateCreated >= @MinDate
        AND tdAfter.DateCreated <= @MaxDate
) AS allRecords
WHERE   tdBefore.AVCClassId <> tdAfter.AVCClassId 
        AND tdBefore.DateCreated >= @MinDate
        AND tdAfter.DateCreated <= @MaxDate

How do I create a column for percentage of total transactions?

如何为总事务的百分比创建列?

3 个解决方案

#1


2  

This worked with your sample data.

这与您的示例数据一致。

DECLARE @MinDate DATETIME = '5/8/2017 12:00AM';
DECLARE @MaxDate DATETIME = '5/8/2017 11:59PM';

WITH cam1 AS ( 
    SELECT TransDetailID,AVClassID
    FROM AVTransDetail
    WHERE CreatedDate BETWEEN @MinDate AND @MaxDate
    AND
    CamID = 1),

cam2 AS (
    SELECT TransDetailID,AVClassID
    FROM AVTransDetail
    WHERE CreatedDate BETWEEN @MinDate AND @MaxDate
    AND
    CamID = 2)

SELECT COUNT(*)'Total',SUM(CASE WHEN c1.AVClassID = c2.AVClassID THEN 0 ELSE 1 END)'NonMatch',
       SUM(CASE WHEN c1.AVClassID = c2.AVClassID THEN 0 ELSE 1 END) * 100.00/COUNT(*)'Percentage'
FROM cam1 c1
     JOIN cam2 c2 ON c1.TransDetailID=c2.TransDetailID

#2


1  

Try the below SQL script.

试试下面的SQL脚本。

First we LAG to find the differences. Then, we get each transaction and whether there is a difference. And finally, we get the percentage.

首先,我们要滞后去发现差异。然后,我们得到每笔交易以及是否有差异。最后,我们得到百分比。

DECLARE @MinDate DATE = '2017/04/06',
        @MaxDate DATE = '2017/05/09';

SELECT count(*) AS TotalTransactions
    ,sum(Change) AS TransactionsWithChange
    ,(cast(sum(Change) AS FLOAT) / cast(count(*) AS FLOAT)) AS ChangePercent
FROM (
    SELECT TransDetailID
        ,MAX(classChange) AS Change
    FROM (
        SELECT *
            ,LAG(AVClassID, 1, AVClassID) OVER (
                PARTITION BY TransDetailID ORDER BY AVDetailID
                ) AS PrevClassId
            ,CASE 
                WHEN LAG(AVClassID, 1, AVClassID) OVER (
                        PARTITION BY TransDetailID ORDER BY AVDetailID
                        ) != AVClassID
                    THEN 1
                ELSE 0
                END AS ClassChange
        FROM AVTransDetail
        where CreatedDate between @MinDate and @MaxDate
        ) AS CoreData
    GROUP BY TransDetailID
    ) AS ChangeData

Hope this helps.

希望这个有帮助。

#3


0  

I added more sample rows to get better result

我添加了更多的示例行以获得更好的结果。

create table #trans (
    AVDetailID int,
    TransDetailID int,
    AVClassID int,
    CamID int,
    CreatedDate datetime
)

insert into #trans values 
( 20101522, 54125478, 5, 1, '2017-05-08 10:15:01:560'),
( 20101523, 54125478, 5, 2, '2017-05-08 10:15:01:620'),
( 20101524, 54125479, 3, 1, '2017-05-08 10:15:03:120'),
( 20101525, 54125479, 2, 2, '2017-05-08 10:15:03:860'),
( 20101526, 54125480, 4, 1, '2017-05-08 10:15:06:330'),
( 20101527, 54125480, 4, 2, '2017-05-08 10:15:06:850'),
( 20101528, 54125481, 4, 1, '2017-05-08 10:15:07:850'),
( 20101529, 54125481, 5, 2, '2017-05-08 10:15:09:850'),
( 20101530, 54125482, 4, 1, '2017-05-08 10:15:07:850'),
( 20101531, 54125482, 5, 3, '2017-05-08 10:15:09:850')

;with diff as (
    -- select records that have different class 
    select CamID as Ent_CamID, count(*) diff_Count
    from #trans ent 
        outer apply (
            select top 1 AVClassID as x_AVClassID, CamID as x_CamID from #trans 
            where CreatedDate > ent.CreatedDate and TransDetailID = ent.TransDetailID
            order by CamID, CreatedDate desc
        ) ext
    where ent.AVClassID <> ext.x_AVClassID
    group by ent.CamID, ext.x_CamID
    union
    select ext.x_CamID as Ext_CamID, count(*) diff_Count
    from #trans ent 
        outer apply (
            select top 1 AVClassID as x_AVClassID, CamID as x_CamID from #trans 
            where CreatedDate > ent.CreatedDate and TransDetailID = ent.TransDetailID
            order by CamID, CreatedDate desc
        ) ext
    where ent.AVClassID <> ext.x_AVClassID
    group by ent.CamID, ext.x_CamID
)
, perc as (
    select Ent_CamID as CamID, sum(diff_Count) Total_Error
    , (select count(*) 
       from #trans where CamID = diff.Ent_CamID 
       group by CamID) AS Total_Capture
    from diff
    group by Ent_CamID
)
select CamID, Total_Error, Total_Capture, 100*(Total_Error)/Total_Capture Error_Percentage
from perc

Result:

结果:

CamID   Total_Error Total_Capture   Error_Percentage
1       3           5               60
2       2           4               50
3       1           1               100

#1


2  

This worked with your sample data.

这与您的示例数据一致。

DECLARE @MinDate DATETIME = '5/8/2017 12:00AM';
DECLARE @MaxDate DATETIME = '5/8/2017 11:59PM';

WITH cam1 AS ( 
    SELECT TransDetailID,AVClassID
    FROM AVTransDetail
    WHERE CreatedDate BETWEEN @MinDate AND @MaxDate
    AND
    CamID = 1),

cam2 AS (
    SELECT TransDetailID,AVClassID
    FROM AVTransDetail
    WHERE CreatedDate BETWEEN @MinDate AND @MaxDate
    AND
    CamID = 2)

SELECT COUNT(*)'Total',SUM(CASE WHEN c1.AVClassID = c2.AVClassID THEN 0 ELSE 1 END)'NonMatch',
       SUM(CASE WHEN c1.AVClassID = c2.AVClassID THEN 0 ELSE 1 END) * 100.00/COUNT(*)'Percentage'
FROM cam1 c1
     JOIN cam2 c2 ON c1.TransDetailID=c2.TransDetailID

#2


1  

Try the below SQL script.

试试下面的SQL脚本。

First we LAG to find the differences. Then, we get each transaction and whether there is a difference. And finally, we get the percentage.

首先,我们要滞后去发现差异。然后,我们得到每笔交易以及是否有差异。最后,我们得到百分比。

DECLARE @MinDate DATE = '2017/04/06',
        @MaxDate DATE = '2017/05/09';

SELECT count(*) AS TotalTransactions
    ,sum(Change) AS TransactionsWithChange
    ,(cast(sum(Change) AS FLOAT) / cast(count(*) AS FLOAT)) AS ChangePercent
FROM (
    SELECT TransDetailID
        ,MAX(classChange) AS Change
    FROM (
        SELECT *
            ,LAG(AVClassID, 1, AVClassID) OVER (
                PARTITION BY TransDetailID ORDER BY AVDetailID
                ) AS PrevClassId
            ,CASE 
                WHEN LAG(AVClassID, 1, AVClassID) OVER (
                        PARTITION BY TransDetailID ORDER BY AVDetailID
                        ) != AVClassID
                    THEN 1
                ELSE 0
                END AS ClassChange
        FROM AVTransDetail
        where CreatedDate between @MinDate and @MaxDate
        ) AS CoreData
    GROUP BY TransDetailID
    ) AS ChangeData

Hope this helps.

希望这个有帮助。

#3


0  

I added more sample rows to get better result

我添加了更多的示例行以获得更好的结果。

create table #trans (
    AVDetailID int,
    TransDetailID int,
    AVClassID int,
    CamID int,
    CreatedDate datetime
)

insert into #trans values 
( 20101522, 54125478, 5, 1, '2017-05-08 10:15:01:560'),
( 20101523, 54125478, 5, 2, '2017-05-08 10:15:01:620'),
( 20101524, 54125479, 3, 1, '2017-05-08 10:15:03:120'),
( 20101525, 54125479, 2, 2, '2017-05-08 10:15:03:860'),
( 20101526, 54125480, 4, 1, '2017-05-08 10:15:06:330'),
( 20101527, 54125480, 4, 2, '2017-05-08 10:15:06:850'),
( 20101528, 54125481, 4, 1, '2017-05-08 10:15:07:850'),
( 20101529, 54125481, 5, 2, '2017-05-08 10:15:09:850'),
( 20101530, 54125482, 4, 1, '2017-05-08 10:15:07:850'),
( 20101531, 54125482, 5, 3, '2017-05-08 10:15:09:850')

;with diff as (
    -- select records that have different class 
    select CamID as Ent_CamID, count(*) diff_Count
    from #trans ent 
        outer apply (
            select top 1 AVClassID as x_AVClassID, CamID as x_CamID from #trans 
            where CreatedDate > ent.CreatedDate and TransDetailID = ent.TransDetailID
            order by CamID, CreatedDate desc
        ) ext
    where ent.AVClassID <> ext.x_AVClassID
    group by ent.CamID, ext.x_CamID
    union
    select ext.x_CamID as Ext_CamID, count(*) diff_Count
    from #trans ent 
        outer apply (
            select top 1 AVClassID as x_AVClassID, CamID as x_CamID from #trans 
            where CreatedDate > ent.CreatedDate and TransDetailID = ent.TransDetailID
            order by CamID, CreatedDate desc
        ) ext
    where ent.AVClassID <> ext.x_AVClassID
    group by ent.CamID, ext.x_CamID
)
, perc as (
    select Ent_CamID as CamID, sum(diff_Count) Total_Error
    , (select count(*) 
       from #trans where CamID = diff.Ent_CamID 
       group by CamID) AS Total_Capture
    from diff
    group by Ent_CamID
)
select CamID, Total_Error, Total_Capture, 100*(Total_Error)/Total_Capture Error_Percentage
from perc

Result:

结果:

CamID   Total_Error Total_Capture   Error_Percentage
1       3           5               60
2       2           4               50
3       1           1               100