July 13, 2006 at 7:29 am
Hi Folks,
I have a database table named Voyage_History that stores the voyage information of our company's vehicles. I have imported data from an MS Excel file and finally I had get the result as screen below:
---------------------------------------
SELECT Voyage_ID,PlateNumber,StartDate from Voyage_End as ddd
Group By Voyage_ID,PlateNumber,StartDate
Voyage_ID PlateNumber StartDate
----------- ----------- ------------------------------------------------------
1 34 DD 0254 2005-12-28 00:00:00
2 34 DD 0254 2005-12-28 00:00:00
3 34 DD 0254 2005-12-30 00:00:00
4 34 DD 0254 2005-12-31 00:00:00
5 34 DD 0254 2006-01-01 00:00:00
6 34 DD 0254 2006-01-04 00:00:00
7 34 DD 0254 2006-01-05 00:00:00
8 34 DD 0254 2006-01-05 00:00:00
9 34 DD 0254 2006-01-06 00:00:00
10 34 DD 0254 2006-01-06 00:00:00
11 34 DD 0254 2006-01-12 00:00:00
12 34 DD 0254 2006-01-13 00:00:00
13 34 DD 0254 2006-01-16 00:00:00
14 34 DD 0254 2006-01-17 00:00:00
15 34 DD 0254 2006-01-17 00:00:00
16 34 DD 0254 2006-01-21 00:00:00
17 34 DD 0254 2006-01-23 00:00:00
18 34 DD 0254 2006-01-26 00:00:00
------------------------------------------------
In fact, voyage_ID 1 and two are same voyage. Because all data is same.
How can I create another table that stores unique Voyage_ID, and the most important part of the question how can I import this data correctly? ( I mean how to determine the same voyages)
Should I have apply a recursive select statement?
July 13, 2006 at 7:45 am
Hi,
Assuming that it is PlateNumber and StartDate that determine a unique voyage then you can simply do the following.
insert into somenewtable
select distinct PlateNumber, StartDate
from Voyage
Hope that helps,
July 13, 2006 at 7:46 am
SELECT z.Voyage_ID,
myt.PlateNumber,
myt.StartDate
FROM (
SELECT MAX(Voyage_ID) Voyage_ID -- Or MIN if you prefer
FROM MyTable
GROUP BY PlateNumber,
StartDate
) z
INNER JOIN MyTable myt ON myt.Voyage_ID = z.Voyage_ID
N 56°04'39.16"
E 12°55'05.25"
July 13, 2006 at 7:49 am
If you only want unique Voyage_ID, this is the query to use
SELECT MAX(Voyage_ID) Voyage_ID -- Or MIN if you prefer
FROM MyTable
GROUP BY PlateNumber,
StartDate
N 56°04'39.16"
E 12°55'05.25"
July 13, 2006 at 8:36 am
Wow...really good results...
Is it possible to move a column from second row to first row? I mean suppose that I made a basic select operation and got the result as below:
---------------------------------------------------------
SELECT Voyage_ID,StartDate,PlateNumber,Driver1 FROM voyage_END
order by startdate
Voyage_ID StartDate PlateNumber Driver1
421 2005-12-28 34 VS 0845 X
750 2005-12-28 34 VS 0845 Y
----------------------------------------------------------------
The MAJOR problem is:
How can I create a new table such as:
Voyage_ID StartDate PlateNumber Driver1 Driver2
421 2005-12-28 34 VS 0845 X Y
difficult case...right?
July 13, 2006 at 9:11 am
I wouldn't say that this is advisable (or the best way to do it necessarily) but you could do it like so:
This assumes that you will always have 2 rows for each voyage (one for each driver).
SELECT z.Voyage_ID,
myt.PlateNumber,
myt.StartDate,
(select Driver from MyTable where myt.PlateNumber = PlateNumber
and myt.StartDate = StartDate and Voyage_Id = z.VoyageId) as Driver1,
(select Driver from MyTable where myt.PlateNumber = PlateNumber
and myt.StartDate = StartDate and Voyage_Id z.VoyageId) as Driver2
FROM (
SELECT MAX(Voyage_ID) Voyage_ID
FROM MyTable
GROUP BY PlateNumber,
StartDate
) z
INNER JOIN MyTable myt ON myt.Voyage_ID = z.Voyage_ID
Personally, I'd look at redesigning the tables to more closely fit the design you're trying to model.
For example, I'd have a Voyage table as above but without the driver column, and a seperate Voyage_Driver table with a foreign key on Voyage_Id to the Voyage table.
That way, every record in the Voyage table is unique. By including Driver1 and Driver2 as columns in the Voyage table you're limiting the design to only ever allow for 2 drivers. What happens if in future you want to model voyages that have more than 2 drivers. It's best to design as generic a design to begin with.
Anyway, that's just food for thought.
Hope this helps,
July 13, 2006 at 9:18 am
The problem is some voyages include one driver and other voyages include two drivers.
I have already designed a database architecture that works well. And this is final step.If I could import the data properly then the problem will be solved..
And..Really thank you for your attention again..
July 13, 2006 at 9:31 am
The above query might still work then - as long as you don't have more than 2 drivers. If there is only 1 driver then the Driver2 subquery will return null.
July 13, 2006 at 12:30 pm
No, it is not difficult at all.
I don't like subqueries much (like SQLZ's solution which do the job), because they take too much time to execute.
Derived tables however I like Try this code for fun
SELECT z.Voyage_ID,
z.PlateNumber,
z.StartDate,
z.Driver1,
CASE WHEN z.Driver2 <> z.Driver1 THEN z.Driver2 END Driver2
FROM (
SELECT StartDate,
PlateNumber,
MIN(Voyage_ID) Voyage_ID,
MIN(Driver1) Driver1,
MAX(Driver1) Driver2
FROM MyTable
GROUP BY StartDate,
PlateNumber
) z
Good luck!
Try my solution and SQL's solution and time them. Use the code below and post the results here...
DECLARE @t DATETIME
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SELECT @t = GETDATE()
SELECT z.Voyage_ID,
z.PlateNumber,
z.StartDate,
z.Driver1,
CASE WHEN z.Driver2 <> z.Driver1 THEN z.Driver2 END Driver2
FROM (
SELECT StartDate,
PlateNumber,
MIN(Voyage_ID) Voyage_ID,
MIN(Driver1) Driver1,
MAX(Driver1) Driver2
FROM MyTable
GROUP BY StartDate,
PlateNumber
) z
PRINT 'Peso solution took ' + STR(DATEDIFF(ms, @t, GETDATE() ), 10) + ' ms'
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SELECT @t = GETDATE()
SELECT z.Voyage_ID,
myt.PlateNumber,
myt.StartDate,
(
select Driver
from MyTable
where myt.PlateNumber = PlateNumber
and myt.StartDate = StartDate
and Voyage_Id = z.VoyageId
) as Driver1,
(
select Driver
from MyTable
where myt.PlateNumber = PlateNumber
and myt.StartDate = StartDate
and Voyage_Id <> z.VoyageId
) as Driver2
FROM (
SELECT MAX(Voyage_ID) Voyage_ID
FROM MyTable
GROUP BY PlateNumber,
StartDate
) z
INNER JOIN MyTable myt ON myt.Voyage_ID = z.Voyage_ID
PRINT 'Sqlz solution took ' + STR(DATEDIFF(ms, @t, GETDATE() ), 10) + ' ms'
N 56°04'39.16"
E 12°55'05.25"
July 13, 2006 at 2:14 pm
I agree, subqueries are cheap and nasty and it was the first thought that came to me. Now that I see you using min and max to get the Driver it seems obvious but at the time it didn't occur to me because of the Driver not being a numeric (I have my stupid moments).
Neat solution .
July 13, 2006 at 11:58 pm
I came to the office right now and applied your solution immediately.
It works like a well designed machine! Thank you for all...And SQLZ, thank you too!
Viewing 11 posts - 1 through 10 (of 10 total)
You must be logged in to reply to this topic. Login to reply