Вопрос № 124152: Уважаемые эксперты, приведённым в приложении запросом я считаю колличество записей с уникальным ip и free равным нулю.
Мне нужно модифицировать данный запрос так, чтобы он возвращал так-же(т.е. сразу 2 значения) колличество уникальных ip с f...Вопрос № 124216: Здравствуйте. Есть оборудование, которое периодически включается и выключается. Данные о статусе оборудования заносятся в таблицу, в которой поля - id(номер оборудования), datestatus(дата изменения статуса), status(1-включили, 0-выключили). То есть i...
Вопрос № 124.152
Уважаемые эксперты, приведённым в приложении запросом я считаю колличество записей с уникальным ip и free равным нулю.
Мне нужно модифицировать данный запрос так, чтобы он возвращал так-же(т.е. сразу 2 значения) колличество уникальных ip с free равным единице.
Спасибо.
select count(distinct(ip)) from lan where free=0 or (free=1) group by free
select count(distinct(ip)),free from lan where free=0 or (free=1) group by free
(кол-во и тип 0 или 1)
--------- Программист - это человек который решает проблему, о которой вы не знаете, способом который вы не понимаете
Ответ отправил: Raptor3 (статус: 5-ый класс)
Ответ отправлен: 21.02.2008, 05:52 Оценка за ответ: 5 Комментарий оценки: Спасибо.
Отвечает: Esi
Здравствуйте, Миленин Александр!
Для этого нужно:
SELECT 0 as prizn_free, COUNT(DISTINCT `ip`) AS `num` FROM `lan` WHERE `free`='0'
union all
SELECT 1 as prizn_free, COUNT(DISTINCT `ip`) AS `num` FROM `lan` WHERE `free`='1'
order by prizn_free
Это один из вариантов.
Удачи!
Ответ отправил: Esi (статус: 3-ий класс)
Ответ отправлен: 21.02.2008, 06:39 Оценка за ответ: 5 Комментарий оценки: Спасибо.
Отвечает: Силантьев А.В.
Здравствуйте, Миленин Александр!
Присоединяюсь к ответу Raptor,
но только ко второй его части.
Первая часть ответа не подходит.
Итак:
select free as `type`, count(distinct(ip)) AS `num`
from lan where free=0 or free=1
group by free
Ответ отправил: Силантьев А.В. (статус: 1-ый класс)
Ответ отправлен: 21.02.2008, 08:52 Оценка за ответ: 5 Комментарий оценки: Спасибо за помощь!
Отвечает: Sergey T
Здравствуйте, Миленин Александр!
Вообще нет особой разницы, что именно использовать - UNION или GROUP BY.
Только например с GROUP BY можно вернуть количество уникальных IP по всем free, которые имеются в таблице. Но если бы мне нужно было толко по двум значениям - я бы наверно воспользовался объединением.
Вот еще несколько вариантов:
- возвращаем количество уникальных IP по всем имеющимся значениям FREE (с сортировкой по FREE)
SELECT 'free', COUNT(DISTINCT('ip')) AS 'num'
FROM 'lan'
GROUP BY 'free'
ORDER BY 'free'
- то же самое, только уже с условием по нужным FREE
SELECT 'free', COUNT(DISTINCT('ip')) AS 'num'
FROM 'lan'
WHERE 'free' IN (0, 1) -- тут перечисляем через запятую все нужные нам FREE
GROUP BY 'free'
ORDER BY 'free'
- с использованием объединения все аналогично ответу ESI, правда можно без ALL, так как значения FREE мы уже ставим уникальные. Но это уже как кому приятнее.
Удачи.
Ответ отправил: Sergey T (статус: 1-ый класс)
Ответ отправлен: 21.02.2008, 09:39 Оценка за ответ: 5 Комментарий оценки: Спасибо за ответ и обьяснения, мне очень помогло.
Отвечает: Zinaida
Здравствуйте, Миленин Александр!Такой запрос можно модифицировать так:
SELECT COUNT(DISTINCT `ip`) AS `num` FROM `lan` WHERE `free`='0'
UNION
SELECT COUNT(DISTINCT `ip`) AS `num` FROM `lan` WHERE `free`='1'
Можно так:
select distinct 'ip', count(*) from 'lan'
where `free`='0' or `free`='1'
group by 'ip'
Ответ отправила: Zinaida (статус: 1-ый класс)
Ответ отправлен: 21.02.2008, 10:31 Оценка за ответ: 5 Комментарий оценки: Спасибо, пользуюсь первым вариантом, во втором видимо проблемы с ковычками.
Отвечает: Синельников Сергей
Здравствуйте, Миленин Александр!
Смею предположить, что из одной записи более удобно получать результаты. А по сему вот:
SELECT COUNT(DISTINCT `ip`*`free`)-1 AS `numfree1`, COUNT(DISTINCT `ip`*(`free`-1))-1 AS `numfree0`FROM `lan` WHERE `free`=0 OR `free`=1
В первом столбце будет для free=1, во втором для free=0
Ответ отправил: Синельников Сергей (статус: 4-ый класс)
Ответ отправлен: 25.02.2008, 21:25 Оценка за ответ: 4 Комментарий оценки: Спасибо, идея очень хорошая, но видимо в реализации ошибка, оба значения всегда равны единице.
Вопрос № 124.216
Здравствуйте. Есть оборудование, которое периодически включается и выключается. Данные о статусе оборудования заносятся в таблицу, в которой поля - id(номер оборудования), datestatus(дата изменения статуса), status(1-включили, 0-выключили). То есть id может повторяться. И есть таблица с выборкой номеров оборудования. Вопрос: каким запросом получить состояние оборудования из второй таблицы на текущий момент? То есть нужно взять id из второй таблицы, найти все записи в первой таблицы с этим id и затем найти запись
с наибольшей датой, и поле status покажет статус оборудования на текущий момент. Результат запроса нужно поместить в табличку с полями - id, status. Вот запрос правильный я и не могу никак составить. БД - MSSQL 2000
Если Вы указываете на конкретный Id и хотите произвести запись в третью таблицу именно по этому Id, а из второй таблицы кроме этого Id больше
ничего не требуется, то можно обратиться сразу к первой таблице и тогда:
insert into t3(id,status)
select t11.id, t11.status
from t1 t11
where t11.id=:id
and t11.datestatus in (select max(datestatus) from t1 t12 where t12.id=:id);
Ответ отправил: Силантьев А.В. (статус: 1-ый класс)
Ответ отправлен: 21.02.2008, 15:58
Отвечает: Sergey T
Здравствуйте, Рыбин Павел!
Данную задачу решить довольно просто тремя способами.
Давайте для начала определимся с нашими таблицами:
Device(id) - это таблица с id устройств,
DeviceStatus(id, datestatus, status) - это таблица, куда пишутся состояния устройств,
RetTable(id, status) - наша таблица.
Первый вариант соответствует стандарту SQL-92 и должен (но не обязан) выполняться на любой платформе БД.
Второй и третий варианты будут работать скорее всего только на SQL SERVER 2000.
Первый на нем тоже будет работать, но я думаю, что 2 и 3 будут предпочтительнее и менее нагрузят сервер при их обработке.
Но это только мои мысли и предположения - в реальности надо тестировать и смотреть.
Да и от размера БД и ее индексации и прочего многое зависит. Но в общем я отвлекся...
Итак! Варианты.
Вариант 1:
INSERT INTO RetTable(id, status)
SELECT d.id, (SELECT s.status FROM DeviceStatus s
WHERE s.id=d.id
AND s.datestatus=(SELECT MAX(w.datestatus) FROM DeviceStatus w
WHERE w.id=s.id))
FROM Device d
ORDER BY d.id
Вариант 2:
INSERT INTO RetTable(id, status)
SELECT d.id, f.status
FROM Device d (NOLOCK)
LEFT JOIN (SELECT s.id, s.status FROM DeviceStatus s (NOLOCK)
WHERE s.datestatus=(SELECT MAX(w.datestatus)
FROM DeviceStatus w (NOLOCK) WHERE w.id=s.id)) f
ON d.id=f.id
ORDER BY d.id
Вариант 3:
INSERT INTO RetTable(id, status)
SELECT d.id, f.status
FROM Device d (NOLOCK)
LEFT JOIN (SELECT s.id, s.status FROM DeviceStatus s (NOLOCK)
INNER JOIN (SELECT id, MAX(datestatus) AS 'datestatus'
FROM DeviceStatus (NOLOCK) GROUP BY id) w
ON s.id=w.id AND s.datestatus=w.datestatus) f
ON d.id=f.id
ORDER BY d.id
Примечание:
Если вам не нужны устройства, по которым нет данных о их состоянии - то во 2 и 3 варианте вместо LEFT JOIN используйте RIGHT JOIN. Работать будет быстрее.
В первом варианте такого сделать нельзя, если конечно в условии не продублировать секцию SELECT - но проще просто удалить потом.
Удачи.
Ответ отправил: Sergey T (статус: 1-ый класс)
Ответ отправлен: 22.02.2008, 14:08