Ответ 1
Правильно, это работает для меня:
SELECT child.*
FROM stack as child,
(SELECT idstack FROM stack WHERE message LIKE '%hello%') as parent
WHERE child.idstack BETWEEN parent.idstack-2 AND parent.idstack+2;
Поведение, которое я хочу реплицировать, похоже на grep с флагами -A
и -B
.
например, grep -A 2 -B 2 "hello" myfile.txt
даст мне все строки, которые имеют "привет" в них, но также 2 строки до и 2 строки после него.
Предположим, что эта схема таблицы:
+--------+-------------------------+
| id | message |
+--------+-------------------------+
| 1 | One tow three |
| 2 | No error in this |
| 3 | My testing message |
| 4 | php module test |
| 5 | hello world |
| 6 | team spirit |
| 7 | puzzle game |
| 8 | social game |
| 9 | stackoverflow |
|10 | stackexchange |
+------------+---------------------+
Теперь запрос вроде:
Select * from theTable where message like '%hello%'
приведет к:
5 | hello world
Как я могу поместить другой параметр "N", который выбирает N строк раньше, и N строк после согласованной записи, т.е. для N = 2, результат должен быть:
| 3 | My testing message |
| 4 | php module test |
| 5 | hello world |
| 6 | team spirit |
| 7 | puzzle game |
id
.Правильно, это работает для меня:
SELECT child.*
FROM stack as child,
(SELECT idstack FROM stack WHERE message LIKE '%hello%') as parent
WHERE child.idstack BETWEEN parent.idstack-2 AND parent.idstack+2;
Не знаю, действительно ли это MySQL, но как насчет
SELECT t.*
FROM theTable t
INNER JOIN (
SELECT id FROM theTable where message like '%hello%'
) id ON id.id <= t.id
ORDER BY
ID DESC
LIMIT 3
UNION ALL
SELECT t.*
FROM theTable t
INNER JOIN (
SELECT id FROM theTable where message like '%hello%'
) id ON id.id > t.id
ORDER BY
ID
LIMIT 2
Попробуйте этот простой (отредактированный) -
CREATE TABLE messages(
id INT(11) DEFAULT NULL,
message VARCHAR(255) DEFAULT NULL
);
INSERT INTO messages VALUES
(1, 'One tow three'),
(2, 'No error in this'),
(3, 'My testing message'),
(4, 'php module test'),
(5, 'hello world'),
(6, 'team spirit'),
(7, 'puzzle game'),
(8, 'social game'),
(9, 'stackoverflow'),
(10, 'stackexchange');
SET @text = 'hello world';
SELECT id, message FROM (
SELECT m.*, @n1:[email protected] + 1 num, @n2:=IF(message = @text, @n1, @n2) pos
FROM messages m, (SELECT @n1:=0, @n2:=0) n ORDER BY m.id
) t
WHERE @n2 >= num - 2 AND @n2 <= num + 2;
+------+--------------------+
| id | message |
+------+--------------------+
| 3 | My testing message |
| 4 | php module test |
| 5 | hello world |
| 6 | team spirit |
| 7 | puzzle game |
+------+--------------------+
Значение N может быть указано как пользовательская переменная; в настоящее время это - "2".
Этот запрос работает с номерами строк, и это гарантирует возврат ближайших записей.
Try
Select * from theTable
Where id >=
(Select id - variableHere from theTable where message like '%hello%')
Order by id
Limit (variableHere * 2) + 1
(только MS SQL Server)
Самый надежный способ - использовать функцию row_number, так что не имеет значения, есть ли пробелы в id. Это также будет работать, если есть несколько случаев результата поиска и правильно вернуть два выше и ниже каждого результата.
WITH
srt AS (
SELECT ROW_NUMBER() OVER (ORDER BY id) AS int_row, [id]
FROM theTable
),
result AS (
SELECT int_row - 2 AS int_bottom, int_row + 2 AS int_top
FROM theTable
INNER JOIN srt
ON theTable.id = srt.id
WHERE ([message] like '%hello%')
)
SELECT theTable.[id], theTable.[message]
FROM theTable
INNER JOIN srt
ON theTable.id = srt.id
INNER JOIN result
ON srt.int_row >= result.int_bottom
AND srt.int_row <= result.int_top
ORDER BY srt.int_row
Добавление ответа с использованием даты вместо идентификатора. В данном случае это таблица поворота по вызову с одной записью в неделю. Из-за изменений идентификатор может быть неработоспособным для намеченной цели. Разумеется, любой прецедент, имеющий несколько записей pr week, pr date или другой, должен быть исправлен.
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| startdate| datetime | NO | | NULL | |
| person | int(11) | YES | MUL | NULL | |
+----------+--------------+------+-----+---------+----------------+
Запрос:
SELECT child.*
FROM rota-table as child,
(SELECT startdate
FROM rota-table
WHERE YEARWEEK(startdate, 3) = YEARWEEK(now(), 3) ) as parent
WHERE
YEARWEEK(child.startdate, 3) >= YEARWEEK(NOW() - INTERVAL 25 WEEK, 3)
AND YEARWEEK(child.startdate, 3) <= YEARWEEK(NOW() + INTERVAL 25 WEEK, 3)