2012-04-11 19 views
3

私は、選択された人物がその曲を知っていてステータスが完了しているときに、その人物の曲名のリストを返すクエリを持っています。質問を選択して、余分なwhere節が必要ですか?

すべての楽器が「該当なし」になっていない場合に、ステータスが完了した曲のみを表示する方法はありますか?

たとえば、テーブルの内容が次のものであるとします。

 
    BandieName SongName Instrument Status 
    Holly  Wipeout  Bells  Complete 
    Holly  Centenial N/A   Complete 
    Charlotte Wipeout  Symbols  Complete 
    Charlotte Centenial N/A   Complete 

私はリストからホリーシャーロットを選択して、クエリを実行した場合、それらの両方がステータス完了して、それらの曲を持っているとして、それは、ワイプアウトと Centenial が一覧表示されます。ただし、Centenialと表示したくないのは、その曲の選択されたすべての人物がN/Aという楽器を持っているためです。内容は以下の通りだった、と私はそれらの3を選択した場合は

することは、私はすべてではないその歌のためにリストされている楽器のがN/であるとして、それは、3つのすべての曲を表示したいと思います。

 
    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

あなたの目標を明確にしましょう:選択したBandieNamesのすべてに曲名を接続し、すべてステータスを完了し、少なくとも1つの楽器(N/Aではない)を選択しますか? –

+0

さて、それは、現時点では、ステータスが完了した、選択されたBandienamesに接続された曲名を得ることができますが、楽器のうちの少なくとも1つがN/Aでない曲名が必要です。 ありがとう – Sophie

+0

何のRDBMSを使用していますか? – GarethD

答えて

0

指定されたすべての名前が曲を持っていてステータスが完了している曲をすべて見つけたら、そのうちの1曲(必ずしもすべてではない)が楽器として "N/A"いくつかのアプローチなどの1:

select s.SongName 
from Learning s 
    left outer join Learning specInstrument on specInstrument.SongName = s.SongName and specInstrument.BandieName = s.BandieName and specInstrument.Instrument <> 'N/A' 
where s.BandieName in ('Holly', 'Charlotte') 
    and s.Status = 'Complete' 
having count (distinct s.BandieName) = 2 
and count(specInstrument.SongName) > 0 

それともマッチング名とそれにリンクのいずれかの人口楽器持って、一致するすべての曲を見つける:あなたはのリストを構築しました明らかに

select s.SongName 
from Learning s 
inner join (select SongName from Learning where status = 'Complete' and BandieName in ('Holly', 'Charlotte') and instrument <> 'N/A') hasInstr on hasInstr.SongName = s.SongName 
where s.BandieName in ('Holly','Charlotte') 
and status = 'Complete' 
group by s.SongName 
having count(distinct s.BandieName) = 2 

をチェックする名前と私が代入した名前の対応する数これは原理を示しています。

+0

これを代表するものは何ですか?またspecInstrument? ありがとう – Sophie

+0

これはテーブルのエイリアスです。基本的には(少し短いですが:-))、意味のある方法でテーブルを参照しています。 Sは曲リスト、specInstrumentは指定された楽器が見つかった。クエリでテーブルが何を表しているかを明示するために便利です(特に、同じテーブルを複数回クエリで使用する場合) – kaj

+0

これは素晴らしい動作です! THnaks – Sophie

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 
+0

元のポスターに聞いたことはまったくないと思います...あなたはBandieNameに制限されず、「Complete」以外のステータスを持つ可能性のある曲が返されています。 –

+0

ステータスは、サブセレクトOPのコメントを読んだ後、私はそれをもっと好きになるように編集します。 – Maess

+0

楽器を選択したものだけでなく、すべてのバンディでステータスを完了する必要がありました。 –

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') 
+0

これを私の現在のコードとどのように統合するのですか?名前はリストボックスのどこにありますか?それに 'count'と 'having'という節がありますか? ありがとう – Sophie

+0

選択したバンディーをループするセクションでは、last exists句で使用されるリストと、繰り返されるexists句(サンプルの最初の2つ)である2つの文字列を作成します。次に、SQLをビルドするときに、SELECT節、FROM節、繰り返しのExists節を記述し、最後にEXISTS節に作成したリストを追加します。 –

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' 
     ) 

あなたは、私はテーブルパラメータを使用してreccomendだろう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 

私はあなたの使い捨ての一部にのを使用して」のカップルを追加しましたしかし、私はあなたのコードを再利用しようとしました。

+0

最初のクエリがすべてのBandyが完了しているかどうかを確認していないため、要件を満たしているとは思えません。それは、少なくとも1つのバンディが完成していることをチェックし、計測器セットを持っています。 –

関連する問題