将 id 值存储为标量变量,然后在第二个查询中使用

Posted

技术标签:

【中文标题】将 id 值存储为标量变量,然后在第二个查询中使用【英文标题】:Store id values as scalar variable to then use in 2nd query 【发布时间】:2022-01-01 06:55:23 【问题描述】:

我认为最好以不同的方式提出这个问题,并专注于我目前遇到问题的特定部分。

所以我有了第一个要使用的查询:

        private const string Items = @"
SELECT 
  id.ItemId, id.ItemDetailID, id.Status, id.Number
, id.Title, id.CreatedDate, id.WithdrawnDate
, RevisionNumber = id.MajorRevisionNumber + ISNULL(id.RevisionNumberOffset, 0)
FROM AgilityItemView v
JOIN ItemDetail id
    ON id.ItemDetailID = v.ItemDetailId
WHERE id.[Status] in ('Released', 'Withdrawn')
AND V.VersionRank = 1 AND V.[Type] = 'Document'";

从这里我想做的是将 id 值存储为标量变量,因为这将在下面的第二个查询中使用:

        private const string LastModifiedDate = @"
WITH History AS (
    SELECT id.ItemID, id.ItemDetailID, ih.ActionedDate
    , ROW_NUMBER() OVER(PARTITION BY id.ItemID ORDER BY ih.ActionedDate DESC) AS vn
    FROM AgilityItemView v
    JOIN ItemDetail id
        ON id.ItemDetailID = v.ItemDetailId
    JOIN ItemHistory ih
        ON ih.ItemDetailID = id.ItemDetailID 
    WHERE id.[Status] in ('Released', 'Withdrawn')
    AND V.VersionRank = 1 AND V.[Type] = 'Document'
    AND ih.Action in (
      'Create','Edit','ItemCreatedByChanged'
    , 'ItemCustomPropertiesChanged','ItemNumberChanged','ItemRoleChanged'
    , 'ItemTitleChanged','Release','Restore'
    , 'ReturnToDraft','Revise','Withdraw'
    )
)
SELECT ItemId, LastModifiedDate = ActionedDate
FROM History
WHERE vn = 1
AND ItemId = @ItemID";

如您所见,标量变量是“@ItemID”。

我将尝试使用这两个查询来创建数据表。然后这些将用于使用 csvhelper 创建一个 csv 文件。此文件的列来自 ExtractDocument.cs 文件。

public record ExtractDocument

    public Guid ItemId  get; init; 
    public string FileType  get; init; 
    public string Status  get; init; 
    public string Number  get; init; 
    public string Title  get; init; 
    public string Function  get; init; 
    public string Discipline  get; init; 
    public string Country  get; init; 
    public string Asset  get; init; 
    public string Language  get; init; 
    public string URLLink  get; init; 
    public string SubmitFeedback  get; init; 
    public string ViewItemLink  get; init; 
    public string CreatedDate  get; init; 
    public DateTime? ReleasedDate  get; init; 
    public string? WithdrawnDate  get; init; 
    public DateTime LastModifiedDate  get; init; 
    public int RevisionNumber  get; init; 
    public string Author  get; init; 
    public string Verifier  get; init; 
    public string Reviewer  get; init; 
    public string Approver  get; init; 
    public string SecurityGroup  get; init;  

 

所以第一个查询将获取以下列的值:ItemID、ItemDetailID、Status、Number、Title、CreatedDate 和 WithDrawnDate。

第二个查询将获取 LastModifiedDate 的值。剩下的还有一些其他的查询,但现在我只专注于让前 2 项工作。

您将能够看到 LastModifiedDate 查询中还有一个 ItemID 列,我要做的是通过 id 匹配上次修改日期。例如,如果第一个查询的 id 为 245,我想要第二个查询的值,其中 id 也是 245,如果有意义的话,将其放在数据表的同一行中?

那么我该怎么做呢?我假设我需要找到一种方法来存储第一个查询中的 id,但我不确定最好的方法。

我试过这个:

    private DataTable GetData(string itemsQuery, string modifiedData, string roleHoldersData, string customPropertiesData, ExtractDocument extract)
    

        var dt = new DataTable();
        var ds = new DataSet();
        using var connection = new SqlConnection(_connectionString);
        using var cnn = new SqlCommand(itemsQuery, connection);

        var adapter = new SqlDataAdapter();

        adapter.SelectCommand = cnn;
        adapter.Fill(ds, "Table(0)");
        adapter.SelectCommand.CommandText = modifiedData;
        cnn.Parameters.AddWithValue("@ItemID", extract.ItemId);
        adapter.Fill(ds, "Table(1)");

        ds.Tables[0].Merge(ds.Tables[1]);
        dt = ds.Tables[0];

        adapter.Fill(dt);

        return dt;

    

但我觉得我对此不太满意,因为它似乎只是将第一个查询存储在数据表中

【问题讨论】:

您使用的是哪个 dbms? 我一直在使用 Microsoft SQL Server,您是这个意思吗? 【参考方案1】:

我不确定如何组合这些查询

您需要重构 SQL 以输出正确的联合数据,这些数据可以转换为 CSV。将其放入存储过程中,并将数据拉入您的程序以将其输出为 CSV。

【讨论】:

我可以理解你在说什么,但我不知道该怎么做。你碰巧有一个这样的好例子的链接吗? 您必须单独研究在您寻求的每个编码范例上要做什么并创建您的代码。似乎没有一个神奇的例子是你要求的......研究然后如果你有个别问题,然后单独询问每个问题,而不是一起询问。换句话说,您需要关注这个问题并研究每个领域。总帐 我不是在寻找一个完美的例子来说明我正在尝试做的事情,只是为了帮助解释你的答案【参考方案2】:

因此,在进行了更多研究之后,似乎最好的方法是将查询合并起来,这样就可以完成我想做的事情,而不是 4 个较小的查询。

这是我最终得到的结果:

        private const string ExtractData = @"
WITH ExtractData AS (
SELECT id.ItemID, id.ItemDetailID, id.Status, id.Number,
id.Title, id.CreatedDate, id.WithdrawnDate, id.ReleaseDate, ih.ActionedDate,
RevisionNumber = id.MajorRevisionNumber + ISNULL(id.RevisionNumberOffset, 0), OwnershipRoleTitle = IOR.Title, 
    HolderTitle = P.Title, CustomPropertyTitle = cp.Title, cpi.ItemTitle
    , ROW_NUMBER() OVER(PARTITION BY id.ItemID ORDER BY ih.ActionedDate DESC) AS vn
FROM AgilityItemView v
JOIN ItemDetail id
ON id.ItemDetailID = v.ItemDetailId
JOIN ItemHistory ih
ON ih.ItemDetailID = id.ItemDetailID
 JOIN dbo.ItemDetailOwnershipRole IDOR
 ON Id.ItemDetailID = IDOR.ItemDetailID
 JOIN dbo.ItemOwnershipRole IOR
    ON IDOR.ItemOwnershipRoleID = IOR.ItemOwnershipRoleID
 JOIN  dbo.ItemDetailOwnershipRoleHolder IDOH
    ON IDOH.ItemDetailOwnershipRoleID = IDOR.ItemDetailOwnershipRoleID
 JOIN  dbo.AgilityItemView P
    ON IDOH.ItemOwnershipRoleHolderItemID = P.ItemID and p.VersionRank = 1
JOIN CustomPropertyItemReference cpir
    ON cpir.ItemDetailID = id.ItemDetailID
JOIN CustomPropertyItem cpi
    ON cpi.CustomPropertyItemID = cpir.ReferenceItemID
JOIN CustomProperty cp
    ON cp.CustomPropertyID = cpi.CustomPropertyID
WHERE id.[Status] in ('Released', 'Withdrawn')
AND V.VersionRank = 1 AND V.[Type] = 'Document'
AND ih.Action in (
      'Create','Edit','ItemCreatedByChanged'
    , 'ItemCustomPropertiesChanged','ItemNumberChanged','ItemRoleChanged'
    , 'ItemTitleChanged','Release','Restore'
    , 'ReturnToDraft','Revise','Withdraw'
    )
AND IOR.Title IN ('Reviewer', 'Drafter', 'Owner', 'Approver')
AND cp.Title in (
'Office Location', 'Governence', 'Type'
, 'HSEQ', 'Approver'
)
    )

SELECT ItemID, ItemDetailId, Status, Number, Title, CreatedDate, ReleaseDate,
WithdrawnDate, LastModifiedDate = ActionedDate, RevisionNumber, OwnershipRoleTitle, HolderTitle,
CustomPropertyTitle, ItemTitle
FROM ExtractData
WHERE vn = 1

;";

【讨论】:

以上是关于将 id 值存储为标量变量,然后在第二个查询中使用的主要内容,如果未能解决你的问题,请参考以下文章

从存储过程完成的第一个插入中提取 id 以在第二个存储过程上使用的麻烦

在第二个查询中查询两个单独的表传递结果,同时仅在第二个查询返回 null 时保留第一个查询的结果

使用javascript为下拉列表赋值

是否可以在 awk 中使用两个不同的字段分隔符并将两者的值存储在变量中?

sp_executesql vs 用户定义的标量函数

Robotframework:在第二个测试用例中找不到套件变量