我有一个查询,当他们都知道该歌曲并且状态已完成时,会返回所选人员的歌曲名称列表。
当所有乐器都没有作为'N / A'时,有没有办法只显示状态完成的歌曲?
例如,假设表格内容如下。
BandieName SongName Instrument Status Holly Wipeout Bells Complete Holly Centenial N/A Complete Charlotte Wipeout Symbols Complete Charlotte Centenial N/A Complete
如果我从列表中选择 Holly 和 Charlotte 并运行查询,它将列出 Wipeout 和 Centenial ,因为他们都将这些歌曲作为状态完成;但是,我不希望它显示 Centenial ,因为该歌曲的所有选定人员都将乐器设为 N / A 。
如果内容如下,我选择了其中的三首,我希望它能显示所有三首歌曲,因为并非所有为该歌曲列出的乐器都是 N / A
BandieName SongName Instrument Status Holly Wipeout Bells Complete Holly Centenial N/A Complete Charlotte Wipeout Symbols Complete Charlotte Centenial N/A Complete Ryan Wipeout Drum Complete Ryan Centenial Drum Complete
到目前为止我的代码是以下代码。
Protected Sub btnGetPlaylist_Click(sender As Object, e As System.EventArgs) Handles btnGetPlaylist.Click
Dim conn As SqlConnection = Nothing
Try
Dim connString As String = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BandDatabase.mdf;Integrated Security=True;User Instance=True"
conn = New SqlConnection(connString)
Dim sqlBandies As String
Dim item As ListItem
For Each item In ListBoxBandies.Items
If item.Selected Then
Dim selectedBandies As String = item.Text
sqlBandies &= "'" & item.Text & "', "
End If
Next
Dim amountSelected As String = ListBoxBandies.Items.Count.ToString
Dim query As String = "select SongName from Learning where BandieName in (" + sqlBandies + " '') AND Status = 'Complete' group by SongName having count(distinct BandieName) = " + ListBoxBandies.GetSelectedIndices.Length.ToString
Dim cmd As SqlCommand = New SqlCommand(query, conn)
conn.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
Dim dt As DataTable = New DataTable()
dt.Load(dr)
GridViewPlaylist.DataSource = dt
GridViewPlaylist.DataBind()
Finally
conn.Close()
End Try
End Sub
答案 0 :(得分:0)
SELECT
BandName
, SongName
, Instrument
, Status
FROM Learning as l1
INNER JOIN (
Select
BandName
, SongName
FROM Learning
WHERE Instrument <> 'N/A' AND Status = 'Complete'
) AS l2
ON l1.BandName = l2.BandName AND l1.SongName = l2.SongName
答案 1 :(得分:0)
这可能不是最有效的搜索,但它应该有效。稍后我可以尝试考虑更有效的解决方案。
SELECT DISTINCT SongName
FROM Learning l1
WHERE
EXISTS (
SELECT *
FROM Learning l2
WHERE l1.BandieName = '<First selected BandieName>'
AND l1.SongName = l2.SongName
AND l2.Status = 'Complete')
AND EXISTS (
SELECT *
FROM Learning l3
WHERE l1.BandieName = '<Second selected BandieName>'
AND l1.SongName = l3.SongName
AND l3.Status = 'Complete')
-- Repeat these for however many people are selected.
AND EXISTS (
SELECT *
FROM Learning lInstrument
WHERE NOT lInstrument = 'N/A'
AND l1.SongName = lInstrument.SongName
AND BandieName IN (<BandieName list>)
AND lInstrument.Status = 'Complete')
答案 2 :(得分:0)
您的查询将是:
WITH LearningCTE AS
( SELECT *
FROM Learning
WHERE BandieName IN ('Holly', 'Charlotte', 'Ryan')
AND Status = 'Complete'
)
SELECT *
FROM LearningCTE a
WHERE EXISTS
( SELECT 1
FROM LearningCTE b
WHERE a.SongName = b.SongName
AND Instrument != 'N/A'
)
如果您使用SQL Server 2008我建议使用表参数而不是在VB.NET中动态构建SQL,那么它将消除SQL注入的任何风险。您需要执行以下操作:
CREATE TYPE NameList AS TABLE (Name VARCHAR(50))
GO
CREATE PROCEDURE dbo.GetPlayList (@Names NameList)
AS
BEGIN
WITH LearningCTE AS
( SELECT l.*
FROM Learning l
INNER JOIN @Names
ON BandieName = Name
WHERE Status = 'Complete'
)
SELECT *
FROM LearningCTE a
WHERE EXISTS
( SELECT 1
FROM LearningCTE b
WHERE a.SongName = b.SongName
AND Instrument != 'N/A'
)
END
然后你可以使用类似于此的VB代码来传递参数
Protected Sub btnGetPlaylist_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGetPlaylist.Click
Dim conn As SqlConnection = Nothing
Try
Dim connString As String = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BandDatabase.mdf;Integrated Security=True;User Instance=True"
conn = New SqlConnection(connString)
Dim NameTable As New DataTable()
NameTable.Columns.Add("Name", GetType(String))
For Each item As ListItem In ListBoxBandies.Items
If item.Selected Then
Dim newRow As DataRow = NameTable.NewRow()
newRow(0) = item.Text
NameTable.Rows.Add(newRow)
End If
Next
Using cmd As SqlCommand = New SqlCommand("dbo.GetPlayList", conn)
cmd.Parameters.Add(New SqlParameter("@Names", NameTable))
cmd.CommandType = CommandType.StoredProcedure
conn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
Dim dt As DataTable = New DataTable()
dt.Load(dr)
GridViewPlaylist.DataSource = dt
GridViewPlaylist.DataBind()
End Using
End Using
Finally
conn.Close()
End Try
End Sub
我已经为你的一些一次性元素添加了一些'使用',但除此之外,我只是尝试重用你的代码。