Как мне выполнить этот сложный запрос в T-SQL / Linq? - PullRequest
3 голосов
/ 16 февраля 2010

В настоящее время у меня есть 2 таблицы

[Category] -> PK| CAT_ID -> CAT_PARENT (link to itself | if it's a top parent category then it's 0)
[Posts] -> PK | POST_ID -> FK | CAT_ID | CREATE_DATE

Как выбрать лучшие 15 строк сообщений в каждом CAT_PARENT, которые имеют несколько дочерних категорий. Таким образом, общее количество сообщений в CAT_PARENT и всех его дочерних элементов составляет всего 15. У нас есть несколько CAT_PARENT. так что мы можем вернуть несколько групп сообщений, которые содержат 15 сообщений для каждого CAT_PARENT и его дочерней категории

Проблема здесь заключается в том, что он выполняется за один цикл запроса к серверу SQL, поскольку один запрос может занимать до 200 сообщений, поэтому было бы лучше, если вы можете записать его в 1 запрос T-sQL / запрос linq.

Я предпочитаю, если вы можете написать это в LINQ. Но это также нормально, чтобы написать это в T-SQL.

Большое спасибо:)


Благодаря решению Александра здесь, я изменил некоторую часть, и она хорошо работает с запросом 186 и некоторым лениво загруженным столбцом менее чем на 2 секунды (удаленно) к моему SQL-серверу

ALTER procedure [dbo].[get_topParentPost] (
    @quantity int
)
as
    WITH t AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY top_level.CAT_ID ORDER BY p.CREATE_DATE DESC) AS row_num, 
    top_level.CAT_ID AS top_level_cat_id, child_category.CAT_ID AS category_id, p.POST_ID, p.CREATE_DATE, p.VALIDATE,
    p.CAT_ID, p.DESCRIPTION, p.DRAF_OF, p.END_DATE, p.MOD_DATE, p.ON_HOMEPAGE, p.PUBLISH_DATE, p.[STATE], p.THUMB_ID, p.TITLE, p.[TYPE],
    p.[VIEW]
    FROM 
        (SELECT cat_id, 0 as cat_parent FROM Categories c WHERE CAT_PARRENT = 0) AS top_level
        INNER JOIN Categories AS child_category  
          ON child_category.CAT_PARRENT = top_level.CAT_ID OR child_category.CAT_ID = top_level.CAT_ID
        INNER JOIN Posts p 
          ON child_category.CAT_ID = p.CAT_ID AND p.VALIDATE = 1
    )
    SELECT * FROM t WHERE row_num <= @quantity

Я изменил часть, которая помогает запросу выбрать 15 лучших по убыванию даты вместо идентификатора по возрастанию

Ответы [ 3 ]

1 голос
/ 16 февраля 2010

Если это для SQL Server 2005 или более поздней версии, вы можете сделать:

SELECT t.top_level_cat_id, t.category_id, t.post_id, t.post_date 
FROM (
    SELECT ROW_NUMBER() OVER (PARTITION BY top_level.cat_id ORDER BY p.post_id) AS row_num, 
        top_level.cat_id AS top_level_cat_id, 
        child_category.cat_id AS category_id, 
        p.post_id, 
        p.post_date
    FROM 
        Post p
        INNER JOIN Category AS child_category 
        ON child_category.cat_id = p.cat_id  
        INNER JOIN Category AS top_level
        ON top_level.cat_id = child_category.cat_parent
) AS t 
WHERE t.row_num <= 15

Вот T-SQL, который я использовал для создания тестовых таблиц:

CREATE TABLE Category (cat_id INT, cat_parent INT);
--top level
INSERT INTO Category VALUES(1, 0);
INSERT INTO Category VALUES(2, 0);
-- child categories
INSERT INTO Category VALUES(3, 1);
INSERT INTO Category VALUES(4, 1);
INSERT INTO Category VALUES(5, 2);

CREATE TABLE Post(post_id INT, cat_id INT, post_date DATETIME);
INSERT INTO Post VALUES(1, 3, GETDATE());
INSERT INTO Post VALUES(2, 3, GETDATE());
INSERT INTO Post VALUES(3, 3, GETDATE());
INSERT INTO Post VALUES(4, 3, GETDATE());
INSERT INTO Post VALUES(5, 3, GETDATE());
INSERT INTO Post VALUES(6, 3, GETDATE());
INSERT INTO Post VALUES(7, 3, GETDATE());
INSERT INTO Post VALUES(8, 3, GETDATE());
INSERT INTO Post VALUES(9, 3, GETDATE());
INSERT INTO Post VALUES(10, 3, GETDATE());
INSERT INTO Post VALUES(11, 3, GETDATE());
INSERT INTO Post VALUES(12, 3, GETDATE());
INSERT INTO Post VALUES(13, 3, GETDATE());
INSERT INTO Post VALUES(14, 3, GETDATE());
INSERT INTO Post VALUES(15, 3, GETDATE());
-- these records won't appear 
INSERT INTO Post VALUES(16, 3, GETDATE());
INSERT INTO Post VALUES(17, 4, GETDATE());
INSERT INTO Post VALUES(18, 4, GETDATE());

INSERT INTO Post VALUES(19, 5, GETDATE());
INSERT INTO Post VALUES(20, 5, GETDATE());
1 голос
/ 16 февраля 2010

Я не уверен, есть ли способ сделать это с помощью linq, не извлекая больше информации, чем необходимо, но вот сценарий T-SQL, который выполнит задачу.Просто чтобы убедиться, что я понял требование, вот мое описание скрипта:

Этот скрипт выбирает 15 лучших записей из таблицы сообщений, категория которых имеет более 1 подкатегорию:

declare @cat_id int
declare MULTIPLE_CHILDREN_CATEGORIES cursor for
(
    select cat_id 
    from categories
    group by cat_parent
    having count(*) > 1
)

open MULTIPLE_CHILDREN_CATEGORIES
fetch next from MULTIPLE_CHILDREN_CATEGORIES into @cat_id

while @@fetch_status = 0
begin
    select top 15 *
    from posts
    where cat_id = @cat_id
    order by create_date desc

    fetch next from MULTIPLE_CHILDREN_CATEGORIES into @cat_id
end

close MULTIPLE_CHILDREN_CATEGORIES
deallocate MULTIPLE_CHILDREN_CATEGORIES
0 голосов
/ 19 февраля 2010

Я представляю что-то вроде этого для linq2sql:

IEnumerable<IEnumerable<Post>> posts = db.Categorys
                        .Where(p=>p.CAT_PARENT == 0)
                        .Select(p=>p.Categorys
                           .SelectMany(q=>q.Posts)
                           .OrderByDescending(q=>q.CREATE_DATE)
                           .Take(15))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...