powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Left Join
24 сообщений из 24, страница 1 из 1
Left Join
    #38116920
Meshel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.
У меня в таблице A хранятся данные в виде:
Код: c#
1.
2.
3.
id name
1  name1
2  name2


В таблице B в виде:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
vId id val tarid
1   1  28  1
2   1  30  2
3   1  27  3
4   1  29  4
5   2  58  1
6   2  60  2
7   2  62  3
8   2  68  4


В итоге нужно получить таблицу:
Код: c#
1.
2.
3.
id name   val1 val2 val3 val4
1  name1  28   30   27   29
2  name2  58   60   62   68


В данном случае tarid 4 вида, но это значение является входным параметром, т.е. изменяется.
Т.е. к таблице A нужно применять left join в данном примере 4 раза, меняя при каждом последущем запросе tarid.
Подскажите, пожалуйста, как это можно сделать, чтоб не лепить цикл?
И, может быть, здесь применить Enumerable.GroupJoin, он сможет вот так перебрать?
...
Рейтинг: 0 / 0
Left Join
    #38116958
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как тебе такой костыль? Я не знаю есть ли в MS SQL всякие хитрые pivot'ы

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
create table t2(id int, name nvarchar(20));
create table t1(id_t2 int, val int, tarid int);

insert into t2(id, name) values(1, 'name 1');
insert into t2(id, name) values(2 'name 2');

insert into t1(id_t2, val, tarid) values(1, 28, 1);
insert into t1(id_t2, val, tarid) values(1, 30, 2);
insert into t1(id_t2, val, tarid) values(1, 27, 3);
insert into t1(id_t2, val, tarid) values(1, 29, 4);
insert into t1(id_t2, val, tarid) values(2, 58, 1);
insert into t1(id_t2, val, tarid) values(2, 60, 2);
insert into t1(id_t2, val, tarid) values(2, 62, 3);
insert into t1(id_t2, val, tarid) values(2, 68, 4);

/* Написать хранимку, которая создает текст запроса ниже и выполняет его */
select t2.name, tmp.*
  from t2 left join
	   (
			  select id_t2,
					 /* Эти строчки текста запроса генерить динамически */
					 min(case tarid when 1 then val else null end) as val1,
					 min(case tarid when 2 then val else null end) as val2,
					 min(case tarid when 3 then val else null end) as val3,
					 min(case tarid when 4 then val else null end) as val4
				from t1
			group by id_t2
	   ) as tmp on t2.id = tmp.id_t2



nameid_t2val1val2val3val4name 1128302729name 2258606268
...
Рейтинг: 0 / 0
Left Join
    #38116963
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord BritishЯ не знаю есть ли в MS SQL всякие хитрые pivot'ы
http://codearticles.ru/Home/Catalogs/403
...
Рейтинг: 0 / 0
Left Join
    #38116969
Meshel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответ.
Сразу не уточнил, мне нужно использовать Linq, т.к. БД разные могуь использоваться.

Т.е. что-то вроде такого (в реальности таблиц больше конечно):
Код: c#
1.
2.
3.
4.
5.
6.
7.
for(i=0;i<3;i++) //значения i=0,1,2 - входная непостоянная последовательность
      {      var q = from m in A
                    join v in B on m.Id equals v.Id into v1
                    from v2 in v1.DefaultIfEmpty()
                    where v2.TfId == i
                    select new { m.Id, v2.TfId };
      }


Вместо for будет использоваться массив со значениями, ну а вот запросы на выходе записывать бы как последущие стобцы, например, в IEnumerable. Т.е. "A" в запросе - тип IEnumerable, "B" - таблица или тоже IEnumerable.
...
Рейтинг: 0 / 0
Left Join
    #38116976
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУ,

Оно у меня просит регистрацию. С моим интернетом зарегать фейкомыльце весьма проблематично.
...
Рейтинг: 0 / 0
Left Join
    #38116978
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Meshelмне нужно использовать Linq, т.к. БД разные могуь использоваться.
Ты опять ничего конкретного не сказал. Тебе нужен LINQ-запрос с трансляцией в SQL или просто локальный цикл?
...
Рейтинг: 0 / 0
Left Join
    #38116979
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord BritishМСУ, Оно у меня просит регистрацию. С моим интернетом зарегать фейкомыльце весьма проблематично.
Регистрация только на скачивание файлов. Вот этого рецепта тебе вполне хватит.
...
Рейтинг: 0 / 0
Left Join
    #38116986
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Meshel
Сразу не уточнил, мне нужно использовать Linq, т.к. БД разные могуь использоваться .




Можно попробовать запилить на Entity SQL + UDF для такой вот гадости min(case tarid when 1 then val else null end). Будете генерить Entity SQL аналогично примеру выше, должно получиться.
...
Рейтинг: 0 / 0
Left Join
    #38116999
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУ, поглядел пример, со стандартным pivot'ом гоже получается, спору нет, спасибо за ссылку.
...
Рейтинг: 0 / 0
Left Join
    #38117000
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Left Join
    #38117010
Meshel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Из Linq будет транслироваться в SQL и использоваться на разных СУБД.
А как можно генерить строчки case?
И можно ли как-нибудь иначе сделать?
...
Рейтинг: 0 / 0
Left Join
    #38117025
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MeshelИз Linq будет транслироваться в SQL и использоваться на разных СУБД.
LINQ-транслятор не поддерживает пивоты, забудь о трансляции.

MeshelА как можно генерить строчки case?
В строку, а после строку на исполнение запроса.

MeshelИ можно ли как-нибудь иначе сделать?
Можно. Написать хранимку, заюзать динамический скрипт или работать с локальной коллекцией.
...
Рейтинг: 0 / 0
Left Join
    #38117029
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Meshel,
я сомневаюсь что они будут транслироваться в sql под разные типы хранилищ (ef), для этого надо писать трансляторы или брать сторонние, и то не все поддерживают ухищренные деревья, в конце концов, код может быть не оптимизирован для конкретной базы.
как например есть недобаза где разработчики даже не знают что такое паддинг и предлагают выкручиваться
через ровнумбер.
Зы может что то изменилось у этого уродца, и появился типа лимит на уровне ядра?
...
Рейтинг: 0 / 0
Left Join
    #38117031
Meshel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, попробую с case, а как можно коллекции использовать?
...
Рейтинг: 0 / 0
Left Join
    #38117032
Meshel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хм, а если не поддерживаются, то как же можно выкрутиться
...
Рейтинг: 0 / 0
Left Join
    #38117037
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиMeshel,
я сомневаюсь что они будут транслироваться в sql под разные типы хранилищ (ef), для этого надо писать трансляторы или брать сторонние, и то не все поддерживают ухищренные деревья, в конце концов, код может быть не оптимизирован для конкретной базы.
как например есть недобаза где разработчики даже не знают что такое паддинг и предлагают выкручиваться
через ровнумбер.
Зы может что то изменилось у этого уродца, и появился типа лимит на уровне ядра?

Oracle? В 12 обещают что вы описываете и default seq.nextval до кучи. На самом деле на фоне ее возможностей это просто мелкая шалость. :)
...
Рейтинг: 0 / 0
Left Join
    #38117040
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Meshel,
изменить выходную структуру, у вас она в любом разе в анонимном типе ляжет на выходе, попробуйте получать в декларированном типе, или получать ее в более ожидаемом ( общепринятом виде)
...
Рейтинг: 0 / 0
Left Join
    #38117042
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Meshel,

На каких СУБД работает твоя приложуха? (Не будет работать, а на каких работает сейчас).

Если хочешь оптимально - пили по хранимке на каждую СУБД и все. Если размерность N про которую ты в топике пишешь фиксирована делай VIEW/MATVIEW. Тебе все варианты предложили уже.
...
Рейтинг: 0 / 0
Left Join
    #38117051
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord BritishЕсли хочешь оптимально - пили по хранимке на каждую СУБД и все.
+1, самый адекватный способ (ну или строковый запрос)

Meshelкак же можно выкрутиться
Ты каким местом читаешь топик. Или по-диогонали чисто?

Lord BritishТебе все варианты предложили уже.
...
Рейтинг: 0 / 0
Left Join
    #38117053
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиизменить выходную структуру, у вас она в любом разе в анонимном типе ляжет на выходе
Не обязательно: 13799062
...
Рейтинг: 0 / 0
Left Join
    #38117073
Meshel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Входная последовательность не фиксирована.
Если использовать коллекции...

Вот список id-шников, полученный из запроса:
Код: c#
1.
IEnumerable<listId> qListId

, где
Код: c#
1.
2.
3.
class listId
{public int id {get; set}
public string name {get;set}}


Далее самое противное и неизвестное. Есть несколько таблиц, которые нужно связать и отправить левым соединением на qListId.
Я выполнил запрос для этих таблиц, получил
Код: c#
1.
IEnumerable<listA> qListA

,где
Код: c#
1.
2.
3.
4.
class listA
{public int idA {get; set}
public string nameA {get;set}
public double vl {get;set}}


Конечно это делать очень нежелательно, т.к. данных тьма получается.
И последним запросом соединяю
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
from l in qListId
join a in qListA on l.id equals a.idA into tmp
from al in tmp.DefaultIfEmpty()
where al.taId == i  //вот это значение входного массива
select new {...}   //пока у меня возвращает типизированное заданное значение, но это не пойдет ,т.к. неизвестно количество элементов входного массива
Может, в последнем запросе задать цикл и в нем, например, к переменной IEnumerable добавлять результат запроса.
Это, наверное, полное извращение...
А должно работать на Oracle,MySQL,SQLite
Надеюсь на Ваше терпение ))
...
Рейтинг: 0 / 0
Left Join
    #38117091
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Meshel,

т.к. БД разные могуь использоваться.

Entity SQL (онанизм)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Data.EntityClient;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication17
{
    class Program
    {
        static void Main(string[] args)
        {

            var esb = new EntityConnectionStringBuilder();
            esb.Metadata = @"res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl";
            esb.Provider = @"System.Data.SqlClient";
            esb.ProviderConnectionString = @"data source=LOCALHOST;initial catalog=DB1;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework";

            using (var connection = new EntityConnection(esb.ConnectionString))
            {
                connection .Open();

                var esql = @"
                        select t2.id as Id, t2.name as Name, tmp.val1 as Val1, tmp.val2 as Val2, tmp.val3 as Val3, tmp.val4 as Val4
                          from DB1Entities1.t2 as t2 left join
	                           (
			                          select t1.id_t2,
					                         min(case when t1.tarid = 1 then t1.val else null end) as val1,
					                         min(case when t1.tarid = 2 then t1.val else null end) as val2,
					                         min(case when t1.tarid = 3 then t1.val else null end) as val3,
					                         min(case when t1.tarid = 4 then t1.val else null end) as val4
				                        from DB1Entities1.t1 as t1
			                        group by t1.id_t2
	                           ) as tmp on t2.id = tmp.id_t2
                    ";
                using (var command = new EntityCommand(esql, connection))
                {
                    var reader = command.ExecuteReader(System.Data.CommandBehavior.SequentialAccess);

                    while (reader.Read())
                    {
                        Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", reader["Id"], reader["Name"],
                            reader["Val1"], reader["Val2"], reader["Val3"], reader["Val4"]);
                    }   
                }
            }
        }
    }
}
...
Рейтинг: 0 / 0
Left Join
    #38117092
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Генеришь текст запроса в коде и вперед.

Если интересно генерируемый SQL
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
SELECT 
[Extent1].[id] AS [id], 
[Extent1].[name] AS [name], 
[GroupBy1].[A1] AS [C1], 
[GroupBy1].[A2] AS [C2], 
[GroupBy1].[A3] AS [C3], 
[GroupBy1].[A4] AS [C4]
FROM  [dbo].[t2] AS [Extent1]
LEFT OUTER JOIN  (SELECT 
	[Extent2].[K1] AS [K1], 
	MIN([Extent2].[A1]) AS [A1], 
	MIN([Extent2].[A2]) AS [A2], 
	MIN([Extent2].[A3]) AS [A3], 
	MIN([Extent2].[A4]) AS [A4]
	FROM ( SELECT 
		[Extent2].[id_t2] AS [K1], 
		CASE WHEN ([Extent2].[tarid] = 1) THEN [Extent2].[val] END AS [A1], 
		CASE WHEN ([Extent2].[tarid] = 2) THEN [Extent2].[val] END AS [A2], 
		CASE WHEN ([Extent2].[tarid] = 3) THEN [Extent2].[val] END AS [A3], 
		CASE WHEN ([Extent2].[tarid] = 4) THEN [Extent2].[val] END AS [A4]
		FROM [dbo].[t1] AS [Extent2]
	)  AS [Extent2]
	GROUP BY [K1] ) AS [GroupBy1] ON [Extent1].[id] = [GroupBy1].[K1]
...
Рейтинг: 0 / 0
Left Join
    #38117119
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мне кажется, тут цена то вопроса
применить универсальный запрос под все типы баз, а нужный формат с генерировать на клиенте, тысячная доли секунды,
select a.name,b.val from a inner join b on (a.id=b.id) order by a.id,b.val
я даже бы order by перенес на клиенте, милый пустяк а серверу полегче
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Left Join
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]