【问题标题】:Getting several lines from a table in SQL Server and list them从 SQL Server 中的表中获取几行并列出它们
【发布时间】:2016-05-09 11:08:59
【问题描述】:

我有一个这样的车辆清单:

假设我只想显示带有 ECU TMS1 和 C200 的汽车。我怎么做?

我已经插入了这个函数:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[SplitString]
        (@pString NVARCHAR(4000), @pDelimiter NCHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
  WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
       E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
       E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
 cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
                     -- for both a performance gain and prevention of accidental "overruns"
                 SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                 SELECT 1 UNION ALL
                 SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
                ),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
                 SELECT s.N1,
                        ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
                   FROM cteStart s
                )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = SUBSTRING(@pString, l.N1, l.L1)
   FROM cteLen l
   WHERE SUBSTRING(@pString, l.N1, l.L1) <> ''
;
GO

并创建了这个存储过程:

Alter Procedure [db_ddladmin].[spGetVehicles]
(
    @ECU nvarchar(20),
    @Identifiers nvarchar(20)
)
AS
Begin 
    SELECT * 
    FROM db_ddladmin.View_VehicleReadouts 
    WHERE ECU IN (SELECT Item FROM [dbo].[SplitString](@ECU,',') )
      AND Identifier IN (SELECT Item FROM [dbo].[SplitString](@Identifiers, ',')) 
END

我通过这个查询执行这个存储过程:

EXEC [db_ddladmin].[spGetVehicles] @ECU = 'EBS7,ALM1', @Identifiers = '88'

我得到一个包含这些 ECU 和标识符的所有车辆的列表。但问题是我只想展示具有我在那里编写的两个 ECU 的车辆,而不是仅具有这些所需 ECU 之一的车辆。我该怎么做?

【问题讨论】:

  • 您没有名为Vehicle 的列。什么可以识别车辆?
  • 一辆车包含不同的ECU,这些不同的ECU可以使用不同的数字来识别,例如88、89。如上图所示,车辆总是有一个名字,在这种情况下“阿米尔”。如前所述,Aamir 包含大约 20 个不同的 ECU,其中每个 ECU 有大约 5 个不同的标识符。

标签: sql sql-server stored-procedures ssms


【解决方案1】:

您可以使用聚合和having 来做到这一点。这个想法是计算匹配的数量:

with items(item) as (
      select Item 
      from dbo.SplitString(@ECU, ',')
     )
select ??
from db_ddladmin.View_VehicleReadouts
where ecu in (select items.item from items)
group by ??
having count(*) = (select count(*) from items);

?? 表示指定车辆的列。

如果表中有重复项,则在having 子句中使用count(distinct ecu) 而不是count(*)

【讨论】:

  • 谢谢。我有点困惑。您说?? 指定了车辆。我不太明白那部分。
  • 我尝试使用您插入的名称??但它给了我同样的结果。它显示具有一个 ECU 但没有另一个的车辆,它还显示重复值@Gordon
  • 如果您使用count(distinct ecu),那么返回的值必须包含所有项目。
  • 感谢您解决了一个问题。我尝试用三个不同的变量来分类车辆。这是我的执行代码EXEC [db_ddladmin].[spGetVehicles] @ECU = 'EBS7, ALM1', @Identifiers = '88', @value ='2459579,2403967' 但它似乎不起作用。我以与定义 ECU 和标识符相同的方式定义 @value。我做错了什么?
猜你喜欢
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
相关资源
最近更新 更多