SQL WHERE IN子查询返回以逗号分隔的列表

时间:2015-08-19 21:21:15

标签: sql sql-server

假设我在SQL表(Locations)中有一个字段,其值为以分号分隔的列表:

username1;username2;username3

如果我说:

SELECT '''' + REPLACE(owners, ';', ''',''') + '''' FROM Locations WHERE ...

我可以输出:

'username1','username2','username3'

...但我想要做的是在子查询中使用它:

SELECT * FROM Users WHERE UserName IN (   
    SELECT '''' + REPLACE(owners, ';', ''',''') + '''' 
    FROM Locations WHERE ...
)

因此,基本上我希望该子查询的输出在IN()子句中充当字符串。这可能吗?

谢谢!

2 个答案:

答案 0 :(得分:5)

不,你不能做你想做的事,在运行时构建'username1','username2','username3'

更简单的解决方案是使用拆分功能

分割功能

CREATE FUNCTION [dbo].[Split]
(
  @delimited nvarchar(max),
  @delimiter nvarchar(100)
) 
RETURNS @t TABLE (id int identity(1,1), val nvarchar(max))
AS
BEGIN
  declare @xml xml
  set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'

  insert into @t(val)
  select
    r.value('.','varchar(max)') as item
  from @xml.nodes('//root/r') as records(r)

  RETURN
END

查询

SELECT *
FROM [Users] u 
WHERE u.UserName IN (  SELECT val 
                       FROM [Location] l
                                    CROSS APPLY [dbo].[Split](l.owners, ';')
                    );

答案 1 :(得分:0)

如果内部选择只返回一行,则可以使用CHARINDEX:

Function Make1bpp(ByVal bmpIN As Bitmap) As Bitmap
    Dim bmpOUT As Bitmap
    bmpOUT = NewBitmap(bmpIN.Width, bmpIN.Height, PixelFormat.Format1bppIndexed)
    bmpOUT.SetResolution(bmpIN.HorizontalResolution, bmpIN.VerticalResolution)

    ' seems like I've got this crap in this program about 100x.
    If bmpIN.PixelFormat <> PixelFormat.Format16bppRgb555 Then
      Throw New ApplicationException("hand-coded routine can only understand image format of Format16bppRgb555 but this image is " & _
        bmpIN.PixelFormat.ToString & ". Either change the format or code this sub to handle that format, too.")
    End If

    ' lock image bytes
    Dim bmdIN As BitmapData = bmpIN.LockBits(New Rectangle(0, 0, bmpIN.Width, bmpIN.Height), _
        Imaging.ImageLockMode.ReadWrite, bmpIN.PixelFormat)
    ' lock image bytes
    Dim bmdOUT As BitmapData = bmpOUT.LockBits(New Rectangle(0, 0, bmpOUT.Width, bmpOUT.Height), _
        Imaging.ImageLockMode.ReadWrite, bmpOUT.PixelFormat)

    ' Allocate room for the data.
    Dim bytesIN(bmdIN.Stride * bmdIN.Height) As Byte
    Dim bytesOUT(bmdOUT.Stride * bmdOUT.Height) As Byte
    ' Copy the data into the PixBytes array. 
    Marshal.Copy(bmdIN.Scan0, bytesIN, 0, CInt(bmdIN.Stride * bmpIN.Height))
    ' > this val = white pix. (each of the 3 pix in the rgb555 can hold 32 levels... 2^5 huh.)
    Dim bThresh As Byte = CByte((32 * 3) * 0.66)
    ' transfer the pixels
    For y As Integer = 0 To bmpIN.Height - 1
      Dim outpos As Integer = y * bmdOUT.Stride
      Dim instart As Integer = y * bmdIN.Stride
      Dim byteval As Byte = 0
      Dim bitpos As Byte = 128
      Dim pixval As Integer
      Dim pixgraylevel As Integer
      For inpos As Integer = instart To instart + bmdIN.Stride - 1 Step 2
        pixval = 256 * bytesIN(inpos + 1) + bytesIN(inpos) ' DEPENDANT ON Format16bppRgb555
        pixgraylevel = ((pixval) And 31) + ((pixval >> 5) And 31) + ((pixval >> 10) And 31)
        If pixgraylevel > bThresh Then ' DEPENDANT ON Format16bppRgb555
          byteval = byteval Or bitpos
        End If
        bitpos = bitpos >> 1
        If bitpos = 0 Then
          bytesOUT(outpos) = byteval
          byteval = 0
          bitpos = 128
          outpos += 1
        End If
      Next
      If bitpos <> 0 Then ' stick a fork in any unfinished busines.
        bytesOUT(outpos) = byteval
      End If
    Next
    ' unlock image bytes
    ' Copy the data back into the bitmap. 
    Marshal.Copy(bytesOUT, 0, _
        bmdOUT.Scan0, bmdOUT.Stride * bmdOUT.Height)
    ' Unlock the bitmap.
    bmpIN.UnlockBits(bmdIN)
    bmpOUT.UnlockBits(bmdOUT)
    ' futile attempt to free memory.
    ReDim bytesIN(0)
    ReDim bytesOUT(0)
    ' return new bmp.
    Return bmpOUT
  End Function