Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.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
T-SQL:在获取多级产品类别时减少查询负载_Sql_Tsql_Sql Server 2016 - Fatal编程技术网

T-SQL:在获取多级产品类别时减少查询负载

T-SQL:在获取多级产品类别时减少查询负载,sql,tsql,sql-server-2016,Sql,Tsql,Sql Server 2016,我正在存储[products]中的产品在[products\u category\u mapping]中分配到的类别。 可以将产品分配到级别0、1和2中的类别。因此,产品将在[products\u category\u mapping]中出现1次、2次或3次,具体取决于产品所分配的级别 然后我想通过查询检索这些产品所属类别的数据。 这些查询非常昂贵,因为它们包含大量联接,我们需要检查每个类别级别的产品是否出现在该级别。另外,大约有20万种产品,每种都被分配到1、2或3个类别,因此运行下面的查询需

我正在存储
[products]
中的产品在
[products\u category\u mapping]
中分配到的类别。 可以将产品分配到级别0、1和2中的类别。因此,产品将在
[products\u category\u mapping]
中出现1次、2次或3次,具体取决于产品所分配的级别

然后我想通过查询检索这些产品所属类别的数据。 这些查询非常昂贵,因为它们包含大量联接,我们需要检查每个类别级别的产品是否出现在该级别。另外,大约有20万种产品,每种都被分配到1、2或3个类别,因此运行下面的查询需要很长时间

我的问题:如何优化这些查询的性能?

注:请不要建议重新设计表格,因为我们正在进行重新设计,这目前是不可行的

当前查询:

SELECT label_nl+';'+slug_nl as labelslug_nl_0,label_en+';'+slug_en as labelslug_en_0,label_nl as label_nl_0,label_en as label_en_0,slug_nl as slug_nl_0,slug_en as slug_en_0
,pagetitle_nl as pagetitle_nl_0,pagetitle_en as pagetitle_en_0,image_nl as image_nl_0,image_en as image_en_0
,description_nl as description_nl_0,description_en as description_en_0
,metadescription_nl as metadescription_nl_0,metadescription_en as metadescription_en_0 
FROM articlegroups ga WITH (NOLOCK)
INNER JOIN products_category_mapping pcm on pcm.articlegroup_id=ga.id
INNER JOIN products gp on gp.id=pcm.artikelid
WHERE gp.id=3216743 AND ga.catlevel=0

SELECT label_nl+';'+slug_nl as labelslug_nl_0,label_en+';'+slug_en as labelslug_en_0,label_nl as label_nl_0,label_en as label_en_0,slug_nl as slug_nl_0,slug_en as slug_en_0
,pagetitle_nl as pagetitle_nl_0,pagetitle_en as pagetitle_en_0,image_nl as image_nl_0,image_en as image_en_0
,description_nl as description_nl_0,description_en as description_en_0
,metadescription_nl as metadescription_nl_0,metadescription_en as metadescription_en_0 
FROM articlegroups ga WITH (NOLOCK)
INNER JOIN products_category_mapping pcm on pcm.articlegroup_id=ga.id
INNER JOIN products gp on gp.id=pcm.artikelid
WHERE gp.id=3216743 AND ga.catlevel=1   

SELECT label_nl+';'+slug_nl as labelslug_nl_2,label_en+';'+slug_en as labelslug_en_2,label_nl as label_nl_2,label_en as label_en_2,slug_nl as slug_nl_2,slug_en as slug_en_2
,pagetitle_nl as pagetitle_nl_2,pagetitle_en as pagetitle_en_2,image_nl as image_nl_2,image_en as image_en_2
,description_nl as description_nl_2,description_en as description_en_2
,metadescription_nl as metadescription_nl_2,metadescription_en as metadescription_en_2 
FROM articlegroups ga WITH (NOLOCK)
INNER JOIN products_category_mapping pcm on pcm.articlegroup_id=ga.id
INNER JOIN products gp on gp.id=pcm.artikelid
WHERE gp.id=3216743 AND ga.catlevel=2
DDL

**更新1**

根据@HABO在下面评论中的建议,我尝试使用案例陈述来组合3个查询:

SELECT
CASE 
    when ga.catlevel=0 THEN
         label_nl+';'+slug_nl as labelslug_nl_0,label_en+';'+slug_en as labelslug_en_0,label_nl as label_nl_0,label_en as label_en_0,slug_nl as slug_nl_0,slug_en as slug_en_0
        ,pagetitle_nl as pagetitle_nl_0,pagetitle_en as pagetitle_en_0,image_nl as image_nl_0,image_en as image_en_0
        ,description_nl as description_nl_0,description_en as description_en_0
        ,metadescription_nl as metadescription_nl_0,metadescription_en as metadescription_en_0 
    when ga.catlevel=1 THEN
         label_nl+';'+slug_nl as labelslug_nl_1,label_en+';'+slug_en as labelslug_en_1,label_nl as label_nl_1,label_en as label_en_1,slug_nl as slug_nl_1,slug_en as slug_en_1
        ,pagetitle_nl as pagetitle_nl_1,pagetitle_en as pagetitle_en_1,image_nl as image_nl_1,image_en as image_en_1
        ,description_nl as description_nl_1,description_en as description_en_1
        ,metadescription_nl as metadescription_nl_1,metadescription_en as metadescription_en_1 
    else null
END
FROM globos_articlegroups ga WITH (NOLOCK)
INNER JOIN globos_products_category_mapping pcm on pcm.articlegroup_id=ga.id
INNER JOIN globos_products gp on gp.id=pcm.artikelid
WHERE gp.id=3216743 AND ga.catlevel in (0,1,2) 
但是,我还不清楚如何确保如何根据cat级别区分列:0、1或2

更新2

我得到了所需的结果集,但它有多行,我想合并成一行。当有多行时,每列的最大值始终为1,其他值为
NULL
。我想将多行合并到一行中,其中每列的最高值(即not
NULL
)将保持不变

当前结果集

  <table>
    <tbody>
      <tr>
        <th>labelslug_nl_0
        </th>
        <th>labelslug_nl_1
        </th>
        <th>labelslug_nl_2
        </th>
      </tr>
      <tr>
        <td>Baby / Geboorte;baby-en-geboorte
        </td>
        <td>NULL
        </td>
        <td>NULL
        </td>
      </tr>
      <tr>
        <td>NULL
        </td>
        <td>Geboortekaartjes;geboorte-kaartjes
        </td>
        <td>NULL
        </td>
      </tr>
    </tbody>
  </table>
  <table>
    <tbody>
      <tr>
        <th>labelslug_nl_0
        </th>
        <th>labelslug_nl_1
        </th>
        <th>labelslug_nl_2
        </th>
      </tr>
      <tr>
        <td>Baby / Geboorte;baby-en-geboorte
        </td>
        <td>Geboortekaartjes;geboorte-kaartjes
        </td>
        <td>NULL
        </td>
      </tr>
    </tbody>
  </table>

labelslug_nl_0
标签标签1
标签标签2
婴儿/格布尔特;格博特婴儿酒店
无效的
无效的
无效的
Geboortekaartjes;格布尔特卡阿特耶斯酒店
无效的
所需结果集

  <table>
    <tbody>
      <tr>
        <th>labelslug_nl_0
        </th>
        <th>labelslug_nl_1
        </th>
        <th>labelslug_nl_2
        </th>
      </tr>
      <tr>
        <td>Baby / Geboorte;baby-en-geboorte
        </td>
        <td>NULL
        </td>
        <td>NULL
        </td>
      </tr>
      <tr>
        <td>NULL
        </td>
        <td>Geboortekaartjes;geboorte-kaartjes
        </td>
        <td>NULL
        </td>
      </tr>
    </tbody>
  </table>
  <table>
    <tbody>
      <tr>
        <th>labelslug_nl_0
        </th>
        <th>labelslug_nl_1
        </th>
        <th>labelslug_nl_2
        </th>
      </tr>
      <tr>
        <td>Baby / Geboorte;baby-en-geboorte
        </td>
        <td>Geboortekaartjes;geboorte-kaartjes
        </td>
        <td>NULL
        </td>
      </tr>
    </tbody>
  </table>

labelslug_nl_0
标签标签1
标签标签2
婴儿/格布尔特;格博特婴儿酒店
Geboortekaartjes;格布尔特卡阿特耶斯酒店
无效的

此单个查询将检索三个查询返回的所有行
CatLevel
0
1
行将填充第一组列,第二组列将填充空值<代码>CatLevel
2
行的作用正好相反

select
  case when AG.CatLevel in ( 0, 1 ) then label_nl + ';' + slug_nl end as labelslug_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then label_en + ';' + slug_en as labelslug_en_0,
  case when AG.CatLevel in ( 0, 1 ) then label_nl end as label_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then label_en end as label_en_0,
  case when AG.CatLevel in ( 0, 1 ) then slug_nl end as slug_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then slug_en end as slug_en_0,
  case when AG.CatLevel in ( 0, 1 ) then pagetitle_nl end as pagetitle_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then pagetitle_en end as pagetitle_en_0,
  case when AG.CatLevel in ( 0, 1 ) then image_nl end as image_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then image_en end as image_en_0,
  case when AG.CatLevel in ( 0, 1 ) then description_nl end as description_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then description_en end as description_en_0,
  case when AG.CatLevel in ( 0, 1 ) then metadescription_nl end as metadescription_nl_0,
  case when AG.CatLevel in ( 0, 1 ) then metadescription_en end as metadescription_en_0,
  case when AG.CatLevel = 2 then label_nl + ';' + slug_nl end as labelslug_nl_2,
  case when AG.CatLevel = 2 then label_en + ';' + slug_en as labelslug_en_2,
  case when AG.CatLevel = 2 then label_nl end as label_nl_2,
  case when AG.CatLevel = 2 then label_en end as label_en_2,
  case when AG.CatLevel = 2 then slug_nl end as slug_nl_2,
  case when AG.CatLevel = 2 then slug_en end as slug_en_2,
  case when AG.CatLevel = 2 then pagetitle_nl end as pagetitle_nl_2,
  case when AG.CatLevel = 2 then pagetitle_en end as pagetitle_en_2,
  case when AG.CatLevel = 2 then image_nl end as image_nl_2,
  case when AG.CatLevel = 2 then image_en end as image_en_2,
  case when AG.CatLevel = 2 then description_nl end as description_nl_2,
  case when AG.CatLevel = 2 then description_en end as description_en_2,
  case when AG.CatLevel = 2 then metadescription_nl end as metadescription_nl_2,
  case when AG.CatLevel = 2 then metadescription_en end as metadescription_en_2
  from ArticleGroups as AG inner join
    Products_Category_Mapping as PCM on PCM.ArticleGroup_Id = AG.Id inner join
    Products as P on P.Id = PCM.ArtikelId
  where P.Id = 3216743 and AG.CatLevel in ( 0, 1, 2 )

请注意,引用的所有列都应包括别名,例如
AG.Label\u NL
。这是留给OP的练习。

请提供精确的优化指标。当您只关心内存占用或最小化争用时,我不愿意花时间减少I/O负载。您的DDL中没有索引?很好。实际上,我的查询执行需要很长时间。我猜这是因为我有3个独立的语句,每个语句都有很多连接。我想知道我是否可以将这3条语句组合成一条更有效的语句。我有一个关于products.id的聚集索引,您会推荐其他什么?这有帮助吗?除非您使用的视图隐藏了一些连接,否则不会出现“很多连接”。(我确实超过了旧项目中查询中联接表的最大数量。如果内存可用,则只有512个。)在索引列上联接通常更快,即索引
products.id
(您有),
products\u category\u mapping.artikelid
products\u category\u mapping.articlegroup\u id
articlegroups.id
articlegroups
上包含
id
catlevel
(按顺序)的索引可能会有帮助,因为
where
子句。检查实际执行计划以查看瓶颈在哪里。Products表的DDl缺少许多列,如[ArtikerNummer]、[titel]etc@Flo如果要将3个查询合并为一个查询,则只会得到一个结果集。当前SELECT语句有3个结果集,每个结果集具有不同的列别名。您的应用程序是否需要这些列别名来区分单独的类别数据?我这样做是为了工作!含糖的只有一件事,结果集现在的行数仍然与找到的catlevel相同,例如,当只找到catlevel=0时,结果集有一行,当找到catlevel 0、1和2时,结果集有三行。有没有办法将结果集合并到一行中?其中
NULL
如果同一列的结果集中的另一行包含值,则会覆盖该值?我想在您的查询中以某种方式使用
MAX
,但不确定如何使用。我希望我在这里清楚地解释了自己:)您应该得到三个查询返回的所有行。要合并行,您需要解释它们是如何分组的。这可能是使用聚合的问题,即
max
groupby
,或者使用
coalesce
组合多行中的值。样本数据和期望的结果应该有助于澄清问题。请参阅我的更新2。为了便于阅读,我省略了大部分专栏。谢谢这可能会令人震惊,但HTML并不是显示示例数据的最可读的方式。而且仍然没有关于行如何分组的指示。似乎您只是想将
max
应用于每一列并返回一行。够简单的吧<代码>选择最大值(当AG.CatLevel在(0,1)中时为大小写,然后将_nl+';'+slug_nl end)标记为labelslug_nl_0,。谢谢。是的,我找不到如何在SO帖子中应用一个像样的表标记。像你的例子一样,一个
案例中的
MAX
对我不起作用,因为我最终不得不将你的
AG.CatLevel拆分为(0,1)<