Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Возможно ли вложить в один запрос все требуемые действия?  [new]
IDVsbruck
Member

Откуда: Украина
Сообщений: 4262
В принципе, к нативному SQL имею крайне малое отношение, все запросы пишу на HQL (Hibernate SQL), которые потом трансформируются ОРМом в обычный SQL с диалектом под нужную ДБ. Однако данный вопрос как бы принципиальный - возможно ли одним запросом? И как его сделать сохраненной процедурой? Но гораздо интересней все же запросом ...

Есть таблица языков:
CREATE TABLE [dbo].[language](
	[id] [varchar](2) NOT NULL,
	[defaultTitle] [varchar](32) NOT NULL,
PRIMARY KEY CLUSTERED 
([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])
ON [PRIMARY]

Есть таблица - некий библиотечный набор:
CREATE TABLE [dbo].[someSet](
	[id] [numeric](19, 0) IDENTITY(1,1) NOT NULL,
	[comment] [varchar](16) NOT NULL,
PRIMARY KEY CLUSTERED 
([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])
ON [PRIMARY]

И таблица языковых меток для этого набора:
CREATE TABLE [dbo].[someSetTitle](
	[id] [numeric](19, 0) IDENTITY(1,1) NOT NULL,
	[title] [varchar](32) NOT NULL,
	[language_id] [varchar](2) NOT NULL,
	[someSet_id] [numeric](19, 0) NOT NULL,
PRIMARY KEY CLUSTERED 
([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])
ON [PRIMARY]

(все вытащил из БД - представление о CREATE самой БД)

Мне нужно вытащить набор с языковыми метками на нужном языке.
Сейчас у меня реализовано достаточно примитивно:
SELECT DISTINCT someSet.id, someSetTitle.title FROM someSet, someSetTitle WHERE someSetTitle.language_id = :lang AND someSetTitle.someSet_id = someSet.id

(не придерживался синтаксиса, написал как пояснение)

Если для всех рекордов из SomeSet есть языковые метки, то все и будут показываться. Однако я бы хотел, чтобы если для какого-то рекорда из someSet нет метки на выбираемом языке, то бралось другое значение (это может быть значение, скажем, на языке "en"; или дефолтное значение из самой таблицы someSet - defaultTitle; или если есть приоритеты у языков, то выбирать от большего к меньшему). То есть чтобы в выборку попали ВСЕ рекорды из someSet (ну, или те, у которых есть буквальное ограничение), а не только те, у которых присутствует метка. И тут возникают сложности ...

Спасибо за совет.
27 окт 12, 23:49    [13386033]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли вложить в один запрос все требуемые действия?  [new]
invm
Member

Откуда: Москва
Сообщений: 9827
select
 ss.someSet_id, sst.language_id
from
 dbo.someSet ss left join
 dbo.someSetTitle sst on sst.someSet_id = ss.someSet_id and sst.language_id = @lang
28 окт 12, 00:15    [13386086]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли вложить в один запрос все требуемые действия?  [new]
SIMPLicity_
Member

Откуда: (((@)))
Сообщений: 8877
IDVsbruck
если для какого-то рекорда из someSet нет метки на выбираемом языке, то бралось другое значение (это может быть значение, скажем, на языке "en"; или дефолтное значение из самой таблицы someSet - defaultTitle; или если есть приоритеты у языков, то выбирать от большего к меньшему


Версия сервера?
Для 2005+ - см. outer apply (для каждой левой строки возвращает, для вашего примера, top 1 ... order by ... из "поджойненной" таблицы).

Ok?
28 окт 12, 00:38    [13386138]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли вложить в один запрос все требуемые действия?  [new]
IDVsbruck
Member

Откуда: Украина
Сообщений: 4262
В настоящий момент 2008 R2, до недавнего была 2005. В будущем не исключаю, что платформа станет *nix, отсюда база сменится, видимо, на MySQL. Поэтому хотелось бы универсальное решение.
28 окт 12, 01:47    [13386275]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли вложить в один запрос все требуемые действия?  [new]
aleks2
Guest
Тормоз - тоже механизм...
select
 ss.someSet_id, sst.language_id
from
 dbo.someSet ss 
 left join
 dbo.someSetTitle sst 
 on sst.someSet_id = ss.someSet_id 
    and 
    (sst.language_id = @lang
     or
     sst.language_id = @lang1 and not exists(select * from dbo.someSetTitle x where x.someSet_id = ss.someSet_id and x.language_id = @lang)
     or
     sst.language_id = @lang2 and not exists(select * from dbo.someSetTitle x where x.someSet_id = ss.someSet_id and x.language_id in (@lang, @lang1) )
     ... -- ну, вы сами понимаете...
    )
28 окт 12, 15:14    [13387128]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли вложить в один запрос все требуемые действия?  [new]
aleks2
Guest
Или в порядке бреда...
declare @l table (language_id int not null, priority int primary key clustered, unique(language_id));

select
 ss.someSet_id, sst.language_id
from
 dbo.someSet ss 
 left join
(
  select z.someSet_id, ll.language_id
  from
	(select st.someSet_id, MIN(l.priority) priority
	   from dbo.someSetTitle st inner join @l l on st.language_id = l.language_id
       group by st.someSet_id
    ) Z
    left outer join @l ll on z.priority = ll.priority
) sst
 on sst.someSet_id = ss.someSet_id 
28 окт 12, 15:26    [13387146]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли вложить в один запрос все требуемые действия?  [new]
IDVsbruck
Member

Откуда: Украина
Сообщений: 4262
Ага, смысл понятен ...
Второе - это хранимка?

Кстати, года полтора назад решал подобную задачу. Только там у меня были языки с приоритетом. Решил таким вот запросом, который, на мой взгляд, слишком заумный (сорри, формат внутренний HQL, неохота подключать старый проект, чтобы посмотреть, что он на выходе выдает):
SELECT OBJECT(section) FROM Sections section 
LEFT JOIN FETCH section.text text 
WHERE (section.direction.id = :directionId) AND (text.locale.locale = :locale OR 
(text.locale.priority IN (SELECT MIN(text2.locale.priority) FROM section.text text2 WHERE (text2.locale.locale <> :locale) 
AND NOT EXISTS(SELECT text3.locale.locale FROM section.text text3 WHERE text3.locale.locale = :locale)))) ORDER BY text.text ASC

Работало вроде нормально, но на выходе был запрос длиной 1000-1200 символов. Для одной одного веб-запроса 4-10 таких запросов, как по мне, многовато, для веб-сервера.

Сообщение было отредактировано: 29 окт 12, 10:40
28 окт 12, 18:12    [13387448]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить