質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • C#

    7444questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • WPF

    724questions

    Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

  • LINQ

    109questions

    LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

LINQでJOINした全てのカラムを一度にSELECTしたい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 730

elvis

score 17

実現したいこと

2つのDataTableをLINQでJOINして、JOINした全ての列をSELECTしたいのですが、
上手く実現できません。一つずつ列を指定する必要があるのでしょうか。
どうかご教示ください。

環境:
visual studio 2013, c#, wpf,
.net Framework4.5
windows7

SQLでしたら以下のように「*」で全列をSELECTする形になります。

SELECT
  fam.*
 ,per.*
FROM dtFamily AS fam
 INNER JOIN dtPerson AS per
 ON fam.familyId = per.familyId

現状

クエリ構文ならびにメソッド構文でJOINは出来てると思います。
(私見ですが)

仕掛中のコード

            //家族テーブル作成
            DataTable dtFamily = new DataTable();
            dtFamily.Columns.Add("familyId", typeof(int));
            dtFamily.Columns.Add("familyName", typeof(string));
            dtFamily.Rows.Add(0, "ishikawa");
            dtFamily.Rows.Add(1, "yamada");
            dtFamily.Rows.Add(2, "kondo");
            dtFamily.Rows.Add(3, "tanaka");

            //個人テーブル作成 
            DataTable dtPerson = new DataTable();
            dtPerson.Columns.Add("familyId", typeof(int));
            dtPerson.Columns.Add("personId", typeof(int));
            dtPerson.Columns.Add("personName", typeof(string));
            dtPerson.Rows.Add(0, 0, "takeo");
            dtPerson.Rows.Add(0, 1, "ruri");
            dtPerson.Rows.Add(0, 2, "takeshi");
            dtPerson.Rows.Add(1, 3, "tarou");
            dtPerson.Rows.Add(1, 4, "hanako");
            dtPerson.Rows.Add(1, 5, "taroko");
            dtPerson.Rows.Add(2, 6, "takuya");
            dtPerson.Rows.Add(2, 7, "chiemi");
            dtPerson.Rows.Add(3, 8, "kaito");
            //DataGrid1.ItemsSource = dt.DefaultView;

            //メソッド構文
            var methodQ = dtPerson.AsEnumerable().Join(
                                       dtFamily.AsEnumerable(),
                                       f => f["familyId"],
                                       p => p["familyId"],
                                       (p, f) => new
                                       {
                                         FamilyName = f["familyName"],
                                         PersonName = p["personName"]
                                   });
            DataGrid1.ItemsSource = methodQ;

            //クエリ構文
            var queryQ =
                from p in dtPerson.AsEnumerable()
                join f in dtFamily.AsEnumerable()
                on p["familyId"] equals f["familyId"]
                select  new {
                     FamilyName = f["familyName"]
                    ,PersonName = p["personName"]};
            DataGrid2.ItemsSource = queryQ;
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

提示コードでは、匿名クラスの{ string, string}が返されますが、その理由は

(p, f) => new
{
    FamilyName = f["familyName"],
    PersonName = p["personName"]
}
//とか
select  new {
    FamilyName = f["familyName"]
    ,PersonName = p["personName"]};


と文字列に限定してSelectを書いているためですよね?

(p, f) => new { FamilyInfo = f, PersonInfo = p}


みたいな返し方をすれば、SQLで言うところの、

  fam.*
 ,per.*


に相当することはできると思います(使うときにどのカラムを取るかを指定できる)。

確かに、fam.*, per.*としたときのような出力にはなりませんが、そこは言語と用途の違いじゃないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/19 16:52

    ご教示いただいた通りに記述すると、DataRaw型でデータを取得することが出来ました。
    ご回答に感謝いたします。

    キャンセル

0

上手く実現できません。

その時のエラーメッセージが表示されていれば質問に載せましょう。エラーメッセージでググれば自分で解決できるかも?

SELECT
  fam.*
 ,per.*
FROM dtFamily AS fam
 INNER JOIN dtPerson AS per
 ON fam.familyId = per.familyId


ではfamilyIdがダブるのでコンピュータはどちらのfamilyIdか困ってしまいます。

SELECT
  fam.*
 ,per.personId
 ,per.personName
FROM dtFamily AS fam
 INNER JOIN dtPerson AS per
 ON fam.familyId = per.familyId


とすることでper.familyIdを除いてSELECTすることでダブりを解消しては?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/19 12:05

    ご回答ありがとうございます。
    早速、試してみます。

    キャンセル

0

以下のようにしてはいかがですか? 質問者さんの開発環境(OS, .NET のバージョンなど・・・質問に書いてくださいね)が不明なので同じにできるかどうかわかりませんが、Windows 10 の .NET 4.6.1 のコンソールアプリで、下のコメントの通りの結果になります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleAppDataTableJoinByLinq
{
    class Program
    {
        static void Main(string[] args)
        {
            //家族テーブル作成
            DataTable dtFamily = new DataTable();
            dtFamily.Columns.Add("familyId", typeof(int));
            dtFamily.Columns.Add("familyName", typeof(string));
            dtFamily.Rows.Add(0, "ishikawa");
            dtFamily.Rows.Add(1, "yamada");
            dtFamily.Rows.Add(2, "kondo");
            dtFamily.Rows.Add(3, "tanaka");

            //個人テーブル作成 
            DataTable dtPerson = new DataTable();
            dtPerson.Columns.Add("familyId", typeof(int));
            dtPerson.Columns.Add("personId", typeof(int));
            dtPerson.Columns.Add("personName", typeof(string));
            dtPerson.Rows.Add(0, 0, "takeo");
            dtPerson.Rows.Add(0, 1, "ruri");
            dtPerson.Rows.Add(0, 2, "takeshi");
            dtPerson.Rows.Add(1, 3, "tarou");
            dtPerson.Rows.Add(1, 4, "hanako");
            dtPerson.Rows.Add(1, 5, "taroko");
            dtPerson.Rows.Add(2, 6, "takuya");
            dtPerson.Rows.Add(2, 7, "chiemi");
            dtPerson.Rows.Add(3, 8, "kaito");

            var query = from p in dtPerson.AsEnumerable()
                        join f in dtFamily.AsEnumerable()
                        on p.Field<int>("familyId") equals f.Field<int>("familyId")
                        select new {
                            FamilyId = f.Field<int>("familyId"),
                            FamilyName = f.Field<string>("familyName"),
                            PersonId = p.Field<int>("personId"),
                            PersonName = p.Field<string>("personName")
                        };

            foreach (var item in query)
            {
                Console.WriteLine("FamiktyId: {0}, FamilyName: {1}, PersonId: {2}, PersonName: {3}",
                    item.FamilyId, item.FamilyName, item.PersonId, item.PersonName);
            }

        // 結果は:
        // FamiktyId: 0, FamilyName: ishikawa, PersonId: 0, PersonName: takeo
        // FamiktyId: 0, FamilyName: ishikawa, PersonId: 1, PersonName: ruri
        // FamiktyId: 0, FamilyName: ishikawa, PersonId: 2, PersonName: takeshi
        // FamiktyId: 1, FamilyName: yamada, PersonId: 3, PersonName: tarou
        // FamiktyId: 1, FamilyName: yamada, PersonId: 4, PersonName: hanako
        // FamiktyId: 1, FamilyName: yamada, PersonId: 5, PersonName: taroko
        // FamiktyId: 2, FamilyName: kondo, PersonId: 6, PersonName: takuya
        // FamiktyId: 2, FamilyName: kondo, PersonId: 7, PersonName: chiemi
        // FamiktyId: 3, FamilyName: tanaka, PersonId: 8, PersonName: kaito
        }
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/19 16:55 編集

    ご丁寧に回答いただき感謝申し上げます。

    以下のように列を指定するのではなく、
    一発で全列をSELECTできないか思案しております。
    サンプルテーブルのような少ない列数だといいのですが、
    列数が増えてくると大変な作業になりますので。。。

    select new {
    FamilyId = f.Field<int>("familyId"),
    FamilyName = f.Field<string>("familyName"),
    PersonId = p.Field<int>("personId"),
    PersonName = p.Field<string>("personName")
    };

    キャンセル

  • 2018/06/19 16:57

    以下のようにDataRowを返すことで、
    実現できました。

    (f, p) =>
    {
    DataRow row = dtResult.NewRow();
    row.ItemArray = p.ItemArray.Concat(f.ItemArray).ToArray();
    dtResult.Rows.Add(row);
    return row;
                 })).ToArray();

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7444questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • WPF

    724questions

    Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

  • LINQ

    109questions

    LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。