Hello this keeps baffling me..

Can I do this in one SQL statement?

SELECT date ;
FROM bookin ;
WHERE part="X" ;
UNION ;
SELECT date ;
FROM bookout ;
WHERE part="X" ;
INTO CURSOR tempbook

SELECT MAX(date) ;
FROM tempbook

--
TIA
Andrew Howell

Re: MAX date from two tables... by Gregory

Gregory
Mon Dec 01 07:19:40 CST 2003

Andrew,

sure

Create cursor BookIN (part c(1), Date D)
insert into BookIN values ('*', date(9999,12,31))
insert into BookIN values ('X', date(2000,1,1))
insert into BookIN values ('X', date(2000,1,2))

Create cursor BookOut (part c(1), Date D)

insert into BookOut values ('*', date(9999,12,31))
insert into BookOut values ('X', date(2001,1,1))
insert into BookOut values ('X', date(2001,1,2))

local aa[1]

select Max(Date) ;
from Bookin ;
into array aa ;
where ( inlist(Part, 'X') ) ;
union ;
select Max(Date) ;
from BookOut ;
where ( inlist(Part, 'X') ) ;
order by 1 desc

do case
case !empty(_Tally)
?'maxdate =', aa[1]

otherwise
?'no data'
endcase

Gregory
___________________________________
"Andrew Howell" <ajh@work> wrote in message
news:%23CY$ogAuDHA.3496@TK2MSFTNGP11.phx.gbl...
> Hello this keeps baffling me..
>
> Can I do this in one SQL statement?
>
> SELECT date ;
> FROM bookin ;
> WHERE part="X" ;
> UNION ;
> SELECT date ;
> FROM bookout ;
> WHERE part="X" ;
> INTO CURSOR tempbook
>
> SELECT MAX(date) ;
> FROM tempbook
>
> --
> TIA
> Andrew Howell
>
>


Re: MAX date from two tables... by Leonid

Leonid
Mon Dec 01 08:15:43 CST 2003

Hi, Andrew

This code seems to work in VFP8, but not in VFP6

create cursor t1 (date D, part C(1))
insert into t1 values ({^2000-01-01},"X")
insert into t1 values ({^2001-01-01},"X")
insert into t1 values ({^2002-01-01},"X")
create cursor t2 (date D, part C(1))
insert into t2 values ({^2000-01-02},"X")
insert into t2 values ({^2001-01-02},"X")
insert into t2 values ({^2002-01-02},"Y")

select =
max(iif(nvl(t1.date,{^1900-01-01})>nvl(t2.date,{^1900-01-01}),t1.date,t2.=
date)) as date ;
from t1 full outer join t2 on t1.date=3Dt2.date ;
where (t1.part is NULL or t1.part=3D"X") ;
and (t2.part is NULL or t2.part=3D"X") ;
into cursor t3

But why do you want to do this in one SQL statement? In two statements =
it's much easier and probably runs faster

Leonid


"Andrew Howell" <ajh@work> wrote in message =
news:#CY$ogAuDHA.3496@TK2MSFTNGP11.phx.gbl...
> Hello this keeps baffling me..
>=20
> Can I do this in one SQL statement?
>=20
> SELECT date ;
> FROM bookin ;
> WHERE part=3D"X" ;
> UNION ;
> SELECT date ;
> FROM bookout ;
> WHERE part=3D"X" ;
> INTO CURSOR tempbook
>=20
> SELECT MAX(date) ;
> FROM tempbook
>=20
> --
> TIA
> Andrew Howell
>=20
>=20


Re: MAX date from two tables... by Andrew

Andrew
Tue Dec 02 07:48:19 CST 2003

Andrew Howell wrote:
> Hello this keeps baffling me..
>
> Can I do this in one SQL statement?
>
> SELECT date ;
> FROM bookin ;
> WHERE part="X" ;
> UNION ;
> SELECT date ;
> FROM bookout ;
> WHERE part="X" ;
> INTO CURSOR tempbook
>
> SELECT MAX(date) ;
> FROM tempbook

Thanks for answers..

OK I simplified things a bit; Gregory your method is OK but I didn't
tell you I want to do this query "the other side" of a union and you cannot
use union in a subquery..

Leonid: Well if 2 run faster then I don't want to do it in one! It's also
FPW2.6a I use..

conclusion: I'll use two SQL statements inside a SCAN..ENDSCAN - I spent
about 2 hours messing about trying to get a single large SQL statement
working and I think Foxpro choked on it TBH, when I split it into smaller
commands the results didn't tally with each other in places that I knew they
should..

Thanks
Andrew Howell



Re: MAX date from two tables... by Andrew

Andrew
Tue Dec 02 08:15:56 CST 2003

Andrew Howell wrote:
> OK I simplified things a bit; Gregory your method is OK but I
> didn't tell you I want to do this query "the other side" of a union
> and you cannot use union in a subquery..
>
> Leonid: Well if 2 run faster then I don't want to do it in one! It's
> also FPW2.6a I use..
>
> conclusion: I'll use two SQL statements inside a SCAN..ENDSCAN - I
> spent about 2 hours messing about trying to get a single large SQL
> statement working and I think Foxpro choked on it TBH, when I split
> it into smaller commands the results didn't tally with each other in
> places that I knew they should..


Just to put it into context; I have the three tables - location, bookin and
bookout. I want to show each location and the date it was last used (if
never used then just show an empty date against the location.)

There are 5 fields that need joining between the tables - 4 for the actual
location and one for the part reference.

This is so easy to say in English and probably impossible in a single SQL
statement for FPW2.6 (and even when I tried it's over a screen of text..)
I'm pretty sure that if I could get the SQL working it would be considerably
faster than the equivalent SCAN..ENDSCAN

I've gone for the SCAN..ENDSCAN because I failed at the other. Because of
needing the UNION..subquery kludge to perform an outer join in FPW2.6, any
further complexity one may add to the SQL is compounded by needing
subqueries all over the place.

Unless I've got it wrong [quite possible, I'm neither good at nor enjoy
SQL-SELECT]

--
Regards
Andrew Howell



Re: MAX date from two tables... by Gregory

Gregory
Tue Dec 02 09:55:40 CST 2003

Hi Andrew,

Do BookIn and BookOut contain a locationID ?\

What is the layout of the location table re join fields ?

I'm pretty sure it can be done in a couple of sql statements and
considerably faster than the scan/endscan

Gregory
_______________________
"Andrew Howell" <ajh@work> wrote in message
news:OO8Gp7NuDHA.2520@TK2MSFTNGP10.phx.gbl...
> Andrew Howell wrote:
> > OK I simplified things a bit; Gregory your method is OK but I
> > didn't tell you I want to do this query "the other side" of a union
> > and you cannot use union in a subquery..
> >
> > Leonid: Well if 2 run faster then I don't want to do it in one! It's
> > also FPW2.6a I use..
> >
> > conclusion: I'll use two SQL statements inside a SCAN..ENDSCAN - I
> > spent about 2 hours messing about trying to get a single large SQL
> > statement working and I think Foxpro choked on it TBH, when I split
> > it into smaller commands the results didn't tally with each other in
> > places that I knew they should..
>
>
> Just to put it into context; I have the three tables - location, bookin
and
> bookout. I want to show each location and the date it was last used (if
> never used then just show an empty date against the location.)
>
> There are 5 fields that need joining between the tables - 4 for the actual
> location and one for the part reference.
>
> This is so easy to say in English and probably impossible in a single SQL
> statement for FPW2.6 (and even when I tried it's over a screen of text..)
> I'm pretty sure that if I could get the SQL working it would be
considerably
> faster than the equivalent SCAN..ENDSCAN
>
> I've gone for the SCAN..ENDSCAN because I failed at the other. Because of
> needing the UNION..subquery kludge to perform an outer join in FPW2.6, any
> further complexity one may add to the SQL is compounded by needing
> subqueries all over the place.
>
> Unless I've got it wrong [quite possible, I'm neither good at nor enjoy
> SQL-SELECT]
>
> --
> Regards
> Andrew Howell
>
>


Re: MAX date from two tables... by Andrew

Andrew
Tue Dec 02 10:26:30 CST 2003

Andrew Howell wrote:
> Just to put it into context; I have the three tables - location,
> bookin and bookout. I want to show each location and the date it was
> last used (if never used then just show an empty date against the
> location.)

Just to add to this; I really, really can't think of a good way to do this
in SQL. I don't think I'm missing anything obvious; it seems like nothing
short of a nightmare in SQL.

I am going to create an index on the bookin and bookout tables with a
combination of part ref and date booked. Then I can scan the location table
and easily locate the last time the part was booked in/out of the bin.

My logic for comparing the part references all the time is that if, for
example, you have some sort of nuts in a location and then change it to
contain bolts: You only want to see when it was last used for the current
part..

--
Regards
Andrew Howell



Re: MAX date from two tables... by Andrew

Andrew
Wed Dec 03 06:16:03 CST 2003

Gregory Adam wrote:
> Hi Andrew,
>
> Do BookIn and BookOut contain a locationID ?\
>
> What is the layout of the location table re join fields ?
>
> I'm pretty sure it can be done in a couple of sql statements and
> considerably faster than the scan/endscan

Thanks for the continued support..
Since you ask I shall put all the gory details here..

* I've tried to put all test cases in;
* A1, 1, 1, 0 - contents changed; used since change
* A1, 1, 1, 1 - contents changed; not used since change
* A1, 1, 1, 2 - something just booked in
* A1, 1, 1, 3 - something just booked out
* A1, 1, 1, 4 - something booked in and out twice
* A1, 1, 1, 5 - something just booked in twice
* A1, 1, 1, 6 - something just booked out twice
* A1, 1, 1, 7 - something booked in and out once
* A1, 1, 1, 8 - not used at all

* expected results:
* british date formats ;)

* A1, 1, 1, 0 - 23/01/2003
* A1, 1, 1, 1 - / / [ie not used]
* A1, 1, 1, 2 - 01/01/2003
* A1, 1, 1, 3 - 15/03/2003
* A1, 1, 1, 4 - 21/01/2003
* A1, 1, 1, 5 - 28/02/2003
* A1, 1, 1, 6 - 14/11/2003
* A1, 1, 1, 7 - 28/11/2003
* A1, 1, 1, 8 - / / [ie not used]


CREATE CURSOR location ;
(spareref N(6,0), ;
contain C(5), ;
store1 C(5), ;
store2 C(5), ;
store3 C(5))
CREATE CURSOR bookout ;
(spareref N(6,0), ;
contain C(5), ;
store1 C(5), ;
store2 C(5), ;
store3 C(5), ;
date D)
CREATE CURSOR bookin ;
(spareref N(6,0), ;
contain C(5), ;
store1 C(5), ;
store2 C(5), ;
store3 C(5), ;
date D)

* populate some bin locations..
INSERT INTO location ;
VALUES (0, 'A1', '1', '1', '0')
INSERT INTO location ;
VALUES (1, 'A1', '1', '1', '1')
INSERT INTO location ;
VALUES (1, 'A1', '1', '1', '2')
INSERT INTO location ;
VALUES (2, 'A1', '1', '1', '3')
INSERT INTO location ;
VALUES (3, 'A1', '1', '1', '4')
INSERT INTO location ;
VALUES (5, 'A1', '1', '1', '5')
INSERT INTO location ;
VALUES (6, 'A1', '1', '1', '6')
INSERT INTO location ;
VALUES (7, 'A1', '1', '1', '7')
INSERT INTO location ;
VALUES (8, 'A1', '1', '1', '8')

* and some things coming out of them
INSERT INTO bookout ;
VALUES (4, 'A1', '1', '1', '0', {13/01/2003})
INSERT INTO bookout ;
VALUES (0, 'A1', '1', '1', '0', {23/01/2003})
INSERT INTO bookout ;
VALUES (3, 'A1', '1', '1', '4', {17/01/2003})
INSERT INTO bookout ;
VALUES (3, 'A1', '1', '1', '4', {21/01/2003})
INSERT INTO bookout ;
VALUES (4, 'A1', '1', '1', '1', {01/01/2003})
INSERT INTO bookout ;
VALUES (2, 'A1', '1', '1', '3', {15/03/2003})
INSERT INTO bookout ;
VALUES (6, 'A1', '1', '1', '6', {13/10/2003})
INSERT INTO bookout ;
VALUES (6, 'A1', '1', '1', '6', {14/11/2003})
INSERT INTO bookout ;
VALUES (7, 'A1', '1', '1', '7', {21/11/2003})

* and some other things going into them..
INSERT INTO bookin ;
VALUES (0, 'A1', '1', '1', '0', {14/01/2003})
INSERT INTO bookin ;
VALUES (1, 'A1', '1', '1', '2', {01/01/2003})
INSERT INTO bookin ;
VALUES (3, 'A1', '1', '1', '4', {19/01/2003})
INSERT INTO bookin ;
VALUES (3, 'A1', '1', '1', '4', {20/01/2003})
INSERT INTO bookin ;
VALUES (5, 'A1', '1', '1', '5', {11/02/2003})
INSERT INTO bookin ;
VALUES (5, 'A1', '1', '1', '5', {28/02/2003})
INSERT INTO bookin ;
VALUES (7, 'A1', '1', '1', '7', {28/11/2003})


--
Regards
Andrew Howell



Re: MAX date from two tables... by Gregory

Gregory
Wed Dec 03 07:34:32 CST 2003

Andrew,

You have A1, 1, 1, 1 in BookOut. So it is used I guess

Here are two possible solutions

2nd one will be faster if yiu have an index on Contain+Store1+store2+store3
in BookIn, BookOut and Location.
It all depends on the data volume

(1) We first get the max dates into a cursor : 2 selects
(2) we select location.* outer join with max dates : 3rd select

*____________________________
&& max dates
select Contain, ;
Store1, ;
store2, ;
store3, ;
Max(date) as date ;
from BookIn ;
into cursor Max_tmp_ ;
group by 1,2,3,4 ;
union ;
select Contain, ;
Store1, ;
store2, ;
store3, ;
Max(date) as date ;
from Bookout ;
group by 1,2,3,4 ;

select Contain, ;
Store1, ;
store2, ;
store3, ;
Max(date) as date ;
from max_tmp_ ;
into cursor max_tmp ;
group by 1,2,3,4


select Location.Contain, ;
location.Store1, ;
location.Store2, ;
location.store3, ;
nvl(max_tmp.date, {}) as Date ;
from location ;
left join max_tmp ;
on ( Location.Contain == max_tmp.Contain ) ;
and ( Location.store1 == max_tmp.store1 ) ;
and ( Location.store2 == max_tmp.store2 ) ;
and ( Location.store3 == max_tmp.store3 ) ;
into cursor Solution1 ;


&& solution 2
select Contain+Store1+store2+store3 as Id, ;
Max(date) as date ;
from BookIn ;
into cursor Max_tmp_ ;
group by 1 ;
union ;
select Contain+Store1+store2+store3 as Id, ;
Max(date) as date ;
from Bookout ;
group by 1

select Id, ;
Max(date) as date ;
from max_tmp_ ;
into cursor max_tmp ;
group by 1


select Location.Contain, ;
location.Store1, ;
location.Store2, ;
location.store3, ;
nvl(max_tmp.date, {}) as Date ;
from location ;
left join max_tmp ;
on ( Contain+Store1+store2+store3 == max_tmp.Id ) ;
into cursor Solution2 ;
order by 1,2,3,4

select Solution1
brow nowait

select Solution2
brow nowait
*------------------------------
"Andrew Howell" <ajh@work> wrote in message
news:e7WlmeZuDHA.2712@tk2msftngp13.phx.gbl...
> Gregory Adam wrote:
> > Hi Andrew,
> >
> > Do BookIn and BookOut contain a locationID ?\
> >
> > What is the layout of the location table re join fields ?
> >
> > I'm pretty sure it can be done in a couple of sql statements and
> > considerably faster than the scan/endscan
>
> Thanks for the continued support..
> Since you ask I shall put all the gory details here..
>
> * I've tried to put all test cases in;
> * A1, 1, 1, 0 - contents changed; used since change
> * A1, 1, 1, 1 - contents changed; not used since change
> * A1, 1, 1, 2 - something just booked in
> * A1, 1, 1, 3 - something just booked out
> * A1, 1, 1, 4 - something booked in and out twice
> * A1, 1, 1, 5 - something just booked in twice
> * A1, 1, 1, 6 - something just booked out twice
> * A1, 1, 1, 7 - something booked in and out once
> * A1, 1, 1, 8 - not used at all
>
> * expected results:
> * british date formats ;)
>
> * A1, 1, 1, 0 - 23/01/2003
> * A1, 1, 1, 1 - / / [ie not used]
> * A1, 1, 1, 2 - 01/01/2003
> * A1, 1, 1, 3 - 15/03/2003
> * A1, 1, 1, 4 - 21/01/2003
> * A1, 1, 1, 5 - 28/02/2003
> * A1, 1, 1, 6 - 14/11/2003
> * A1, 1, 1, 7 - 28/11/2003
> * A1, 1, 1, 8 - / / [ie not used]
>
>
> CREATE CURSOR location ;
> (spareref N(6,0), ;
> contain C(5), ;
> store1 C(5), ;
> store2 C(5), ;
> store3 C(5))
> CREATE CURSOR bookout ;
> (spareref N(6,0), ;
> contain C(5), ;
> store1 C(5), ;
> store2 C(5), ;
> store3 C(5), ;
> date D)
> CREATE CURSOR bookin ;
> (spareref N(6,0), ;
> contain C(5), ;
> store1 C(5), ;
> store2 C(5), ;
> store3 C(5), ;
> date D)
>
> * populate some bin locations..
> INSERT INTO location ;
> VALUES (0, 'A1', '1', '1', '0')
> INSERT INTO location ;
> VALUES (1, 'A1', '1', '1', '1')
> INSERT INTO location ;
> VALUES (1, 'A1', '1', '1', '2')
> INSERT INTO location ;
> VALUES (2, 'A1', '1', '1', '3')
> INSERT INTO location ;
> VALUES (3, 'A1', '1', '1', '4')
> INSERT INTO location ;
> VALUES (5, 'A1', '1', '1', '5')
> INSERT INTO location ;
> VALUES (6, 'A1', '1', '1', '6')
> INSERT INTO location ;
> VALUES (7, 'A1', '1', '1', '7')
> INSERT INTO location ;
> VALUES (8, 'A1', '1', '1', '8')
>
> * and some things coming out of them
> INSERT INTO bookout ;
> VALUES (4, 'A1', '1', '1', '0', {13/01/2003})
> INSERT INTO bookout ;
> VALUES (0, 'A1', '1', '1', '0', {23/01/2003})
> INSERT INTO bookout ;
> VALUES (3, 'A1', '1', '1', '4', {17/01/2003})
> INSERT INTO bookout ;
> VALUES (3, 'A1', '1', '1', '4', {21/01/2003})
> INSERT INTO bookout ;
> VALUES (4, 'A1', '1', '1', '1', {01/01/2003})
> INSERT INTO bookout ;
> VALUES (2, 'A1', '1', '1', '3', {15/03/2003})
> INSERT INTO bookout ;
> VALUES (6, 'A1', '1', '1', '6', {13/10/2003})
> INSERT INTO bookout ;
> VALUES (6, 'A1', '1', '1', '6', {14/11/2003})
> INSERT INTO bookout ;
> VALUES (7, 'A1', '1', '1', '7', {21/11/2003})
>
> * and some other things going into them..
> INSERT INTO bookin ;
> VALUES (0, 'A1', '1', '1', '0', {14/01/2003})
> INSERT INTO bookin ;
> VALUES (1, 'A1', '1', '1', '2', {01/01/2003})
> INSERT INTO bookin ;
> VALUES (3, 'A1', '1', '1', '4', {19/01/2003})
> INSERT INTO bookin ;
> VALUES (3, 'A1', '1', '1', '4', {20/01/2003})
> INSERT INTO bookin ;
> VALUES (5, 'A1', '1', '1', '5', {11/02/2003})
> INSERT INTO bookin ;
> VALUES (5, 'A1', '1', '1', '5', {28/02/2003})
> INSERT INTO bookin ;
> VALUES (7, 'A1', '1', '1', '7', {28/11/2003})
>
>
> --
> Regards
> Andrew Howell
>
>


Re: MAX date from two tables... by Andrew

Andrew
Wed Dec 03 09:26:27 CST 2003

Gregory, it is nothing short of altruistic of you to have waded through my
last post. Sincerest thanks. Basically I've adapted your ideas with the
comments below [if you're interested..]

Gregory Adam wrote:
> Andrew,
>
> You have A1, 1, 1, 1 in BookOut. So it is used I guess

It was booked out, but with a different part. Nothing significant, it's just
a case of adding spareref to the four location fields as the join condition.
I still haven't decided if this is a good idea or not ;)

>
> Here are two possible solutions
>
> 2nd one will be faster if yiu have an index on
> Contain+Store1+store2+store3 in BookIn, BookOut and Location.
> It all depends on the data volume

2nd one it is!
I have a bit more fun because I use FPW2.6a and LEFT JOIN doesn't exist, one
has to use a combination of a NOT EXISTS subquery UNIONED with an INNER JOIN
to achieve the same.

Maybe my database design is not great, we have a similar system that has a
transaction table which covers both booking in and booking out with an extra
field denoting in or out. This caused its own problems with certain queries
and I decided to have two separate tables when I made this. I still think
for the most part it is better with separate tables but as I said, it's so
simple in English to state the requirement but it's not straightforward in
SQL...

--
Thanks again
Andrew Howell



Re: MAX date from two tables... by Gregory

Gregory
Wed Dec 03 09:50:38 CST 2003

Andrew,

Did not know it was fpw2.6a


Append this just after solution2.. It does not use a left join and neither
a subquery and should be fast

Success,

*-----------------------------------------------------
&& solution 3
select max_tmp
index on Id tag Id

select Location.Contain, ;
location.Store1, ;
location.Store2, ;
location.store3, ;
iif(seek(Contain+Store1+store2+store3, 'max_tmp'), max_tmp.date, {}) as
date ;
from Location ;
into cursor Solution3 ;
order by 1,2,3,4

select Solution3
brow nowait
*----------------------------------------------------
"Andrew Howell" <ajh@work> wrote in message
news:ejxteHbuDHA.2244@TK2MSFTNGP09.phx.gbl...
> Gregory, it is nothing short of altruistic of you to have waded through my
> last post. Sincerest thanks. Basically I've adapted your ideas with the
> comments below [if you're interested..]
>
> Gregory Adam wrote:
> > Andrew,
> >
> > You have A1, 1, 1, 1 in BookOut. So it is used I guess
>
> It was booked out, but with a different part. Nothing significant, it's
just
> a case of adding spareref to the four location fields as the join
condition.
> I still haven't decided if this is a good idea or not ;)
>
> >
> > Here are two possible solutions
> >
> > 2nd one will be faster if yiu have an index on
> > Contain+Store1+store2+store3 in BookIn, BookOut and Location.
> > It all depends on the data volume
>
> 2nd one it is!
> I have a bit more fun because I use FPW2.6a and LEFT JOIN doesn't exist,
one
> has to use a combination of a NOT EXISTS subquery UNIONED with an INNER
JOIN
> to achieve the same.
>
> Maybe my database design is not great, we have a similar system that has a
> transaction table which covers both booking in and booking out with an
extra
> field denoting in or out. This caused its own problems with certain
queries
> and I decided to have two separate tables when I made this. I still think
> for the most part it is better with separate tables but as I said, it's so
> simple in English to state the requirement but it's not straightforward in
> SQL...
>
> --
> Thanks again
> Andrew Howell
>
>