Гость
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Left Join / 24 сообщений из 24, страница 1 из 1
20.01.2013, 17:05
    #38116920
Meshel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
Здравствуйте.
У меня в таблице 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
20.01.2013, 18:07
    #38116958
Lord British
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
Как тебе такой костыль? Я не знаю есть ли в 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
20.01.2013, 18:19
    #38116963
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
Lord BritishЯ не знаю есть ли в MS SQL всякие хитрые pivot'ы
http://codearticles.ru/Home/Catalogs/403
...
Рейтинг: 0 / 0
20.01.2013, 18:29
    #38116969
Meshel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
Спасибо за ответ.
Сразу не уточнил, мне нужно использовать 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
20.01.2013, 18:38
    #38116976
Lord British
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
МСУ,

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




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

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

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

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

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

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

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

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

Вот список 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
20.01.2013, 21:29
    #38117091
Lord British
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
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
20.01.2013, 21:33
    #38117092
Lord British
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
Генеришь текст запроса в коде и вперед.

Если интересно генерируемый 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
20.01.2013, 22:24
    #38117119
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Left Join
мне кажется, тут цена то вопроса
применить универсальный запрос под все типы баз, а нужный формат с генерировать на клиенте, тысячная доли секунды,
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
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Left Join / 24 сообщений из 24, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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