:: Игры Разума
Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
Итак имеется родительская таблица tbChel - в ней ключевое поле - KLUCH - C(10), Name C(10) имя человека, nKab C(2) - номер (допустим кабинета) начальный, Номер конечный -nKabEnd C(2)
И дочерняя таблица - tbPereezd в которой нет собственного уникального номера, но есть родительский kluch, а также поле даты DataPereez D, номер кабинета из какого перехали nKabIZ C(2), номер кабинета куда перехали nKab С(2)
Нам нужно проверить таблицу на корректность заполнения. А именно:
1. Самый первый перезд должен быть из "начального" кабинета родительской таблицы.
2. Самый последний перезд должен быть в "конечный" кабинет
3. "Цепочка" кабинтов должна быть непрерывна.
Каждый пункт один Select запрос возвращающий имена людей с некорректными данными.

P.S. Конечно дублирование и не отвечает нормализации, но что делать?
Ratings: 0 negative/0 positive
Re: Еще игра
PaulWist

Сообщений: 14618
Дата регистрации: 01.04.2004
Слав, ты бы хоть код создания таблиц привёл, а то ломает самому писать


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
Что то запарился простите
CREATE CURSOR tbChel (kluch c(20), Name C(10), nKab C(2) , NKab1 C(2))
CREATE CURSOR tbPereezd (kluch c(20),DataPereez D, nKabIz C(2) , NKab C(2))
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Маша], [20], [20])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Саша], [10], [30])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [10], [30])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Коля], [12], [13])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [11], [13]) &&Ошибка первого типа
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Вася], [01], [11])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [01], [12]) &&Ошибка второго типа
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Вася], [02], [03])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [02], [05])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-8, [05], [04])
INSERT INTO tbPereezd VALUES (lcKluch, DATE(), [05], [03]) &&Ошибка третьего типа
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
Вроде бы элементарная задача, на на фоксе превращается в головоломку.

Вот так первый пункт должен решаться на нормальном SQL:
SELECT a.*;
FROM tbChel a;
WHERE a.nKab <>;
(SELECT TOP 1 b.nKabIz FROM tbPereezd b;
WHERE a.kluch = b.kluch;
ORDER BY b.DataPereez)
Но фокс выдает "запросы этого типа не поддерживаются"...

Дальше начинаются игры с уникальностью DataPereez и т.п., фоксовые извраты SQL... Вот поэтому я начиная с 6-ки БД делаю на MSSQL и с фоксовым SQL страюсь дела не иметь.
Ratings: 0 negative/0 positive
Re: Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
Вместо неравно попробуй not in
Ratings: 0 negative/0 positive
Re: Еще игра
Foxtrot

Сообщений: 3408
Откуда: Куда:
Дата регистрации: 25.04.2003
Твой код формирования таблиц чуток подправил = добавил тебя в список
CREATE CURSOR tbChel (kluch c(20), NAME c(10), nKab c(2) , NKab1 c(2))
CREATE CURSOR tbPereezd (kluch c(20),DataPereez D, nKabIz c(2) , nKab c(2))
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Маша], [20], [20])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Саша], [10], [30])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [10], [30])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Коля], [12], [13])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [11], [13])
lcKluch = SYS(2015)
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [01], [12])
INSERT INTO tbChel VALUES (lcKluch , [Вася], [01], [11])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Слава], [02], [03])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [02], [05])
INSERT INTO tbPereezd VALUES (lcKluch, DATE(), [05], [03])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-8, [05], [04])
SELECT tbChel.kluch, tbChel.NAME FROM tbChel;
INNER JOIN tbPereezd ON tbChel.kluch = tbPereezd.kluch;
WHERE tbChel.nKab NOT IN (SELECT tbPereezd.nKabIz FROM tbPereezd);
GROUP BY 1,2 &&INTO CURSOR C1
SELECT tbChel.kluch, tbChel.NAME FROM tbChel;
INNER JOIN tbPereezd ON tbChel.kluch = tbPereezd.kluch;
WHERE tbChel.NKab1 NOT IN (SELECT tbPereezd.nKab FROM tbPereezd);
GROUP BY 1,2 &&INTO CURSOR C2
SELECT tbChel.kluch, tbChel.NAME FROM tbChel;
INNER JOIN tbPereezd ON tbChel.kluch = tbPereezd.kluch;
INNER JOIN tbPereezd tbPereezd2 ON tbPereezd.kluch=tbPereezd2.kluch;
AND tbPereezd.DataPereez<tbPereezd2.DataPereez;
AND tbPereezd.nKab # tbPereezd2.nKabIz;
GROUP BY 1,2 &&INTO CURSOR C3


------------------
Мойте ноги, моя ноги вы моете и руки




Исправлено 1 раз(а). Последнее : Foxtrot, 15.03.07 13:37
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
Foxtrot
Насколько я вижу, это не решение. Достаточно чуть усложнить/пополнить условие/данные:

CREATE CURSOR tbChel (kluch c(20), NAME c(10), nKab c(2) , NKab1 c(2))
CREATE CURSOR tbPereezd (kluch c(20),DataPereez D, nKabIz c(2) , nKab c(2))
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Маша], [20], [20])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Саша], [10], [30])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [10], [30])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Коля], [12], [13])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [11], [12]) && ошибка 1-го рода
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-8, [12], [13])
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Вася], [01], [11])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [01], [11])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-5, [11], [12]) && ошибка 2-го рода
lcKluch = SYS(2015)
INSERT INTO tbChel VALUES (lcKluch , [Слава], [02], [03])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-10, [02], [05])
INSERT INTO tbPereezd VALUES (lcKluch, DATE()-8, [05], [04])
INSERT INTO tbPereezd VALUES (lcKluch, DATE(), [05], [03]) && ошибка 3-го рода

Предлагаю использовать именно эти данные.
Ratings: 0 negative/0 positive
Re: Еще игра
leonid

Сообщений: 3204
Откуда: Рига
Дата регистрации: 03.02.2006
А я еще предлагаю добавить условие, что один человек в один день не может переезжать два раза (или это и так предполагалось?), а то третий пункт без него становится непонятным.
Ratings: 0 negative/0 positive
Re: Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
Предполагалось.
Нам нужно проверить таблицу на корректность заполнения.
0. Нельзя чтобы несколько переездов было в один день...
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
Неа. Так нечестно. ;)

Тут получится тогда что дата является ключом, а вот попробуйте-ка такое решить если даты переездов у человека повторяются!

Впрочем, ладно, я погорячился, пусть будет такое условие.



Исправлено 1 раз(а). Последнее : Prudivus, 15.03.07 17:05
Ratings: 0 negative/0 positive
Re: Еще игра
leonid

Сообщений: 3204
Откуда: Рига
Дата регистрации: 03.02.2006
Наверно это далеко не оптимальный вариант, но все-таки
Create Cursor tbChel (kluch c(20), Name c(10), nKab c(2) , NKab1 c(2))
Create Cursor tbPereezd (kluch c(20),DataPereez D, nKabIz c(2) , nKab c(2))
lcKluch = Sys(2015)
Insert Into tbChel Values (lcKluch , [Masha], [20], [20])
lcKluch = Sys(2015)
Insert Into tbChel Values (lcKluch , [Sasha], [10], [30])
Insert Into tbPereezd Values (lcKluch, Date()-10, [10], [30])
lcKluch = Sys(2015)
Insert Into tbChel Values (lcKluch , [Pasha], [12], [13])
Insert Into tbPereezd Values (lcKluch, Date()-10, [11], [12])
Insert Into tbPereezd Values (lcKluch, Date()-8, [12], [13])
lcKluch = Sys(2015)
Insert Into tbChel Values (lcKluch , [Dasha], [01], [11])
Insert Into tbPereezd Values (lcKluch, Date()-10, [01], [11])
Insert Into tbPereezd Values (lcKluch, Date()-5, [11], [12])
lcKluch = Sys(2015)
Insert Into tbChel Values (lcKluch , [Glasha], [02], [03])
Insert Into tbPereezd Values (lcKluch, Date()-10, [02], [05])
Insert Into tbPereezd Values (lcKluch, Date()-8, [05], [04])
*Insert Into tbPereezd Values (lcKluch, Date()-3, [04], [03])
Insert Into tbPereezd Values (lcKluch, Date(), [05], [03])
Select kluch, Name From tbChel Where Exist ;
(Select nKabIz From tbPereezd t0 Where t0.kluch=tbChel.kluch) ;
and nKab Not In ;
(Select nKabIz From tbPereezd t1 Where t1.kluch=tbChel.kluch And DataPereez = ;
(Select Min(DataPereez) From tbPereezd t2 Where t2.kluch=t1.kluch))
Select kluch, Name From tbChel Where Exist ;
(Select nKabIz From tbPereezd t0 Where t0.kluch=tbChel.kluch) ;
and NKab1 Not In ;
(Select nKab From tbPereezd t1 Where t1.kluch=tbChel.kluch And DataPereez = ;
(Select Max(DataPereez) From tbPereezd t2 Where t2.kluch=t1.kluch))
Select kluch, Name From tbChel Where kluch In ;
(Select Distinct t5.kluch From ;
(Select t3.kluch, t3.DataPereez, t3.nKab, Min(t4.DataPereez) As DataNext From ;
tbPereezd t3 Join tbPereezd t4 On ;
t3.kluch=t4.kluch And t3.DataPereez<t4.DataPereez ;
GROUP By t3.kluch, t3.DataPereez, t3.nKab) t5 ;
JOIN tbPereezd t7 On t5.kluch=t7.kluch And t5.DataNext=t7.DataPereez ;
WHERE t5.nKab<>t7.nKabIz)
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
Посмотрел первый (и второй) селект. По-моему вполне рабочий вариант! Я позволил себе немного оптимизировать его:

Select c.kluch, c.Name;
From tbChel c;
JOIN tbPereezd t ON t.kluch=c.kluch;
Where c.nKab <> t.nKabIz;
AND t.DataPereez = ;
(Select Min(DataPereez) From tbPereezd t2 Where t2.kluch=c.kluch)
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
А по поводу третьего селекта и задания: мне кажется такое на SQL не делается вообще, без циклов/рекурсий не очень представляю себе...
Ratings: 0 negative/0 positive
Re: Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
2 Prudivus
это еще почему??
2 leonid
Первые два я делал приблизительно также.
Третий чуть по другому.
SELECT * FROM tbChel WHERE kluch in ;
(select tb_1.kluch FROM tbPereezd tb_1 ;
INNER JOIN tbPereezd tb_2 ON tb_2.kluch = tb_1.kluch ;
WHERE tb_1.nKab<>tb_2.nKabIz and ;
tb_2.DataPereez >tb_1.DataPereez ;
AND tb_2.DataPereez in ;
(SELECT MIN(DataPereez ) FROM tbPereezd tb_3 ;
WHERE tb_1.kluch=tb_3.kluch AND tb_3.DataPereez >tb_1.DataPereez ))
Надо бы сравнить скорости...
А вообще
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
Да, по поводу третьего я был не прав - решается. Но хотелось увидеть комментарии к решениям, с объяснением что и почему. (навскидку мне кажется что оба приведенных решения неточны/неполны)
Ratings: 0 negative/0 positive
Re: Еще игра
leonid

Сообщений: 3204
Откуда: Рига
Дата регистрации: 03.02.2006
Prudivus
Но хотелось увидеть комментарии к решениям, с объяснением что и почему.
Я тут двое суток был вдали от интернета, сейчас посмотрел на свое решение - как там сделано уже все забыл, а разобраться - черт ногу сломит. Поэтому, вполне допускаю, что
Цитата:
навскидку мне кажется что оба приведенных решения неточны/неполны
Посмотрел авторское решение - сначала показалось, что там что-то не так, потом, что все путем, а проверить на работе не могу - девятки нет, а на шестерке все это не работает.
А вообще, мое мнение, что если такие вещи писать на фоксе, то лучше все это делать не одним оператором, а несколькими, загоняя промежуточные результаты в курсоры. Отлаживать это будет несравненно проще, читаемость тоже существенно повысится, и сдается мне что почти всегда и скорость выполнения можно сделать не хуже.
Ratings: 0 negative/0 positive
Re: Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
В моем случае это было невозможно потому что начиная от оператора Where в select код должен был присутствовать в мем поле и работать по скану. ТО бишь полностью код выглядит примерно/схематично так:
Create cursor tal (Id I,MistakeName C(10), ChelName C(10))
i=i+1
Select MistakeVvod
SCAN
lcWhereUsl= MistakeVvod.lcUsl
lcName = MistakeVvod.lcName
i=i+1
insert into tal ;
select i as Name,lcName as MistakeName, * from tbChel where &lcWhereUsl
ENDSCAN
Под рукой Fox'a нет, пишу в Опере по памяти, поэтому - если что извиняйте...
Ratings: 0 negative/0 positive
Re: Еще игра
Zakharov_slava
Автор

Сообщений: 2022
Откуда: Алматы
Дата регистрации: 14.10.2005
Prudivus
Да, по поводу третьего я был не прав - решается. Но хотелось увидеть комментарии к решениям, с объяснением что и почему. (навскидку мне кажется что оба приведенных решения неточны/неполны)
Код - самодокументируемыйся.
А вообще так:
kluch in ; && Проверяю есть ли ключ в
(select tb_1.kluch FROM tbPereezd tb_1 ; && Соеденяю каждый перезд со следующим
INNER JOIN tbPereezd tb_2 ON tb_2.kluch = tb_1.kluch ; && Tb_1 - текущий переезд
WHERE tb_1.nKab<>tb_2.nKabIz and ; && Проверка на сам факт ошибки
tb_2.DataPereez >tb_1.DataPereez ; && Tb_2 - следующий переезд
AND tb_2.DataPereez in ; && Вот здесь проверяю чтоб следующий был ближайший
(SELECT MIN(DataPereez ) FROM tbPereezd tb_3 ; && Выбираю самый ранний переезд
WHERE tb_1.kluch=tb_3.kluch AND tb_3.DataPereez >tb_1.DataPereez )) && Старше "текущего"
Надеюсь чем то помог...
Ratings: 0 negative/0 positive
Re: Еще игра
leonid

Сообщений: 3204
Откуда: Рига
Дата регистрации: 03.02.2006
Я вчера погонял оба варианта на скорость. Результаты вообще говоря не очень. Оба варианта жрут много памяти, а когда она кончается, начинаются резкие тормоза. На 3000 записях я уже не дождался. Оба варианта занимают время пропорционально N^2, где N - это количество записей (я проверял только при одном значении ключа). Сдается мне, что если писать в несколько операторов, то легко можно достичь если не линейной зависимости, то по крайней мере N*lnN. Может быть этого можно достичь и с одним оператором, но как-то не приходит в голову как. Вот код, на котором я тестировал
Create Cursor tbChel (kluch c(20), Name c(10), nKab c(2) , NKab1 c(2))
Create Cursor tbPereezd (kluch c(20),DataPereez D, nKabIz c(2) , nKab c(2))
LOCAL m.fk, m.nk, m.ok, m.sc, i
RAND(-1)
lcKluch = Sys(2015)
m.fk=INT(RAND()*90+1)
m.ok=m.fk
FOR i=1 TO 1000
m.nk=INT(RAND()*90+1)
IF m.nk=m.ok
m.nk=m.nk+1
ENDIF
Insert Into tbPereezd Values (lcKluch , DATE()+i, PADL(m.ok,2,"0"), PADL(m.nk,2,"0"))
m.ok=m.nk
IF i%100=0
WAIT WINDOW ALLTRIM(STR(i)) NOWAIT
endif
next
Insert Into tbChel Values (lcKluch , [Glasha], PADL(m.ok,2,"0"), PADL(m.nk,2,"0"))
*!* SELECT tbPereezd
*!* GO 900
*!* replace nKabIz WITH PADL(VAL(nKabIz)+1,2,"0")
*!* INDEX on kluch TAG kluch
*!* INDEX on datapereez TAG datapereez
WAIT clear
clear
SET TALK window
SET TALK on
m.sc=SECONDS()
Select kluch, Name From tbChel Where kluch In ;
(Select Distinct t5.kluch From ;
(Select t3.kluch, t3.DataPereez, t3.nKab, Min(t4.DataPereez) As DataNext From ;
tbPereezd t3 Join tbPereezd t4 On ;
t3.kluch=t4.kluch And t3.DataPereez<t4.DataPereez ;
GROUP By t3.kluch, t3.DataPereez, t3.nKab) t5 ;
JOIN tbPereezd t7 On t5.kluch=t7.kluch And t5.DataNext=t7.DataPereez ;
WHERE t5.nKab<>t7.nKabIz) INTO CURSOR tmp
?SECONDS()-m.sc
BROWSE
m.sc=SECONDS()
SELECT * FROM tbChel WHERE kluch in ;
(select tb_1.kluch FROM tbPereezd tb_1 ;
INNER JOIN tbPereezd tb_2 ON tb_2.kluch = tb_1.kluch ;
WHERE tb_1.nKab<>tb_2.nKabIz and ;
tb_2.DataPereez >tb_1.DataPereez ;
AND tb_2.DataPereez in ;
(SELECT MIN(DataPereez ) FROM tbPereezd tb_3 ;
WHERE tb_1.kluch=tb_3.kluch AND tb_3.DataPereez >tb_1.DataPereez )) INTO CURSOR tmp
?SECONDS()-m.sc
BROWSE
SET TALK off
SET TALK nowindow
Ratings: 0 negative/0 positive
Re: Еще игра
Prudivus

Сообщений: 4283
Откуда: Кишинев
Дата регистрации: 14.12.2006
Разбирал код Леонида, все корректно, у Славы, видимо, тоже. Так что я был неправ. Но понять "с наскоку" не смог, видимо в голове не сложился шаблон на подобные задачи, никогда с таким не сталкивался. А ключом к решению (то чего хотелось в комментах) является "Соеденяю каждый перезд со следующим" (с) Слава.
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 5 (Гостей: 5)

© 2000-2024 Fox Club 
Яндекс.Метрика