MySQL Migration Script Help - sql

I am working on a site that lists a directory of various restaurants, and currently in the process of switching to a newer CMS. The problem I have is that both CMSes represent the restaurant data differently.
Old CMS
A Cross Reference Database so it may list an entry for an example like this:
ID / FieldID / ItemID / data
3 / 1 / 6 / 123 Foo Street
4 / 2 / 6 / Bar
One reference table that reference FieldID 1 as street, FieldID 2 as City.
Another reference table that references ItemID 6 as Delicious Restaurant.
New CMS
The way the database is on the new CMS when I set up a sample listing, is all direct rows, no cross referencing. So instead the data for the same restaurant will be:
ID / Name / Street / City
3 / Delicious Restaurant / 123 Foo Street / Bar
There are about 2,000 restaurant listings so it's not a HUGE amount in terms of SQL row data size, but of course enough to not even consider re-entering all the restaurant listings by hand.
I have a few ideas, but it would be extremely dirty and take a while, and I'm not a MySQL expert so I am here for some ideas how I should tackle it.
Many thanks to those who can help.

You can join against the data table multiple times to get something like this:
insert into newTable
select oldNames.ItemID,
oldNames.Name,
oldStreets.data,
oldCities.data
from oldNames
inner join oldData as oldStreets on oldNames.ItemID = oldStreets.ItemID
inner join oldData as oldCities on oldNames.ItemID = oldCities.ItemID
inner join oldFields as streetsFields
on oldStreets.FieldID = streetsFields.FieldID
and streetsFields.Name = 'Street'
inner join oldFields as citiesFields
on oldCities.FieldID = citiesFields.Field
and citiesFields.Name = 'City'
You didn't provide names for all of the tables, so I made some names up. If you have more fields that you need to extract, it should be trivial to extend this sort of query.

Related

When was “Checked” added and who added it - SQL

I'm beginning to study SQL queries and attempting to understand some more difficult ones. I have these 2 tables:
User
ID_user
Name
Tracking
ID_Track
Old_Value
New_Value
Date_Entered
ID_user
The data entry interface looks like this:
User Column Date Old Value New Value
David (assistant) Status 02/2022 Pending Processing
David (assistant) address 02/2022 Miami New York City
David (assistant) Type 02/2022 House Apartment
David(assistant) Size 02/2022 Small Big
Peter(QA) Size 06/2022 - Medium
Peter(QA) Status 06/2022 - Checked
I'm trying to figure out how to join User and Tracking tables in order to know when the word “Checked” was added and who added it.
know when the word Checked was added and who added it
You can filter the tracking table for the keyword, and then bring the user name with a join on the user table:
select t.*, u.name
from tracking t
inner join user u on u.id_user = t.id_user
where t.new_value = 'Checked'
You can add more conditions in the where clause if you need more filtering criteria.

SQL - Find the horses that have run at ONLY 1 specific track

I have some horse data in a table and am practicing SQL while following my hobby. I would like to find an elegant way to solve this problem. Right now I have this convoluted way of getting the answer but I know there HAS to be an easier way.
Description:
I'll make it really simple (Assume these 8 rows are the entire table). I have a table with 4 columns. HORSE_ID, NAME, TRACK, Date
A horse might run at one track or many different tracks. The end goal is to find what only the horses who have ran/campaigned at only one specific track....in this case, I want to see the horses that have run all their races at SA (Santa Anita)
HORSE_ID NAME TRACK DATE
1 JUSTIFY SA FEB-2018
2 JUSTIFY PIM MAY-2018
3 JUSTIFY BEL JUN-2018
4 KANTHAKA SA DEC-2017
5 KANTHAKA SA JAN-2018
7 THREE RULES GP JUL-2016
8 DABSTER SA JAN-2018
So if I ran this query with this data, the only horses I would expect to see are KANTHAKA, and DABSTER because they are the only horses that only ran all their races at Santa Anita track. So say next month KANTHAKA ran at ANOTHER DIFFERENT track, then the next time the query was run, only DABSTER would show up.
Does this make sense?
Try using GROUP BY with HAVING:
SELECT NAME
FROM yourTable
GROUP BY NAME
HAVING MIN(TRACK) = MAX(TRACK);
Writing the HAVING clause as above is preferable to writing HAVING COUNT(DISTINCT TRACK) = 1. The reason for this is that the above query can make use of an index on (NAME, TRACK).
If in addition you wish to restrict to a single track, then we can try:
SELECT NAME
FROM yourTable
GROUP BY NAME
HAVING MIN(TRACK) = MAX(TRACK) AND MIN(TRACK) = 'SA';
You can do a subquery requesting the count of distinct tracks to be 1 using GROUP BY and HAVING COUNT DISTINCT and then select those WHERE the track is 'SA':
SELECT NAME
FROM
(SELECT NAME, MIN(TRACK) as TRACK
FROM HORSES
GROUP BY 1
HAVING COUNT (DISTINCT TRACK) = 1) horses_one_race
WHERE
TRACK = 'SA'

Add columns to SQL query output

I have searched this site and others, and I am unable to find a clear answer, so here I am. In the below query, I will get an output with a single column for the county. What I would like to do can only be described in Excel parlance as transpose the counties so each county for a brand family is in its own column. I have played around with using pivot, but unfortunately do not fully grasp what would be required. This is not my first query, but I am relatively new to SQL scripting, so please ask any clarification questions and I will do my best to answer.
Some of the brand families have 10 counties and some have 20, so some of the columns would be blank. This is for an in-house DB, not the SO DB, running on SQL Server 2008R2, FWIW.
The script is:
select distinct b.reckey as BrandFamilyKey, b.recname as BrandFamilyName,
g.recname as County
from territories as t
left join dbo.TerritoryBrandFamilies as tbf on tbf.TerritoryNid = t.TerritoryNid
left join Customers as c on c.TerritoryNid = t.TerritoryNid
left join GeographicAreas as g on g.GeoAreaNid = c.GeoAreaNid
left join brandfamilies as b on b.brandfamilynid = tbf.brandfamilynid
where t.activeflag = 1 AND C.GeoAreaNid IS NOT NULL and b.activeflag = 1
order by b.RecName,g.recname
the output would look like
brand family 1 county 1
brand family 1 county 2
brand family 1 county 3
What I would like to see is:
brand family 1 county 1 county 2 county 3

Hibernate criteria left join with query

I have two classes Apartment and AdditionalSpace representing tables as below.
Apartment table
ID AREA SOLD
---- ------ ----
1 100 1
2 200 0
AdditionalSpace table
ID AREA APARTMENTID
---- ------ -----------
10 10 1
11 10 1
12 10 1
20 20 2
21 20 2
As you can see Apartment's table has a one-to-many relation with AdditionalSpace table, i.e. Apartment.ID=AdditionalSpace.APARTMENTID.
Question:- How to retrieve total area of a sold apartment including its additional space area.
The SQL which I have used so far to retrieve similar result is :-
select sum(apt.area + ads.adsarea) from apartment apt left outer join (select sum(area) as adsarea, apartmentid from additionalspace group by apartmentid) ads on ads.apartmentid=apt.id where apt.sold=1
I am struggling to find a way in order to implement the above scenario via criteria instead of SQL/HQL. Please suggest. Thanks.
I don't think this is possible in criteria. The closest I can see is to simply get the size of the apartment and the sum of the additional areas as two columns in your result, like this:
Criteria criteria = session.createCriteria(Apartment.class,"a");
criteria.createAlias("additionalSpaces", "ads");
criteria.setProjection(Projections.projectionList()
.add(Projections.property("area"))
.add(Projections.groupProperty("a.id"))
.add(Projections.sum("ads.area")));
Alternatively, if you still want to use Hibernate but are happy to write it in HQL, you can do the following:
select ads.apartment.id,max(a.area)+sum(ads.area)
from Apartment a
join a.additionalSpaces ads
group by ads.apartment.id
This works because HQL allows you to write the + to add together the two projections, but I don't know that an analogous method exists on the projections api.

How to make SQL query that will combine rows of result from one table with rows of another table in specific conditions in SQLite

I have aSQLite3 database with three tables. Sample data looks like this:
Original
id aName code
------------------
1 dog DG
2 cat CT
3 bat BT
4 badger BDGR
... ... ...
Translated
id orgID isTranslated langID aName
----------------------------------------------
1 2 1 3 katze
2 1 1 3 hund
3 3 0 3 (NULL)
4 4 1 3 dachs
... ... ... ... ...
Lang
id Langcode
-----------
1 FR
2 CZ
3 DE
4 RU
... ...
I want to select all data from Original and Translated in way that result would consist of all data in Original table, but aName of rows that got translation would be replaced with aName from Translated table, so then I could apply an ORDER BY clause and sort data in the desired way.
All data and table designs are examples just to show the problem. The schema does contain some elements like an isTranslated column or translation and original names in separate tables. These elements are required by application destination/design.
To be more specific this is an example rowset I would like to produce. It's all the data from table Original modified by data from Translated if translation is available for that certain id from Original.
Desired Result
id aName code isTranslated
---------------------------------
1 hund DG 1
2 katze CT 1
3 bat BT 0
4 dachs BDGR 1
... ... ... ...
This is a typcial application for the CASE expression:
SELECT Original.id,
CASE isTranslated
WHEN 1 THEN Translated.aName
ELSE Original.aName
END AS aName,
code,
isTranslated
FROM Original
JOIN Translated ON Original.id = Translated.orgID
WHERE Translated.langID = (SELECT id FROM Lang WHERE Langcode = 'DE')
If not all records in Original have a corresponding record in Translated, use LEFT JOIN instead.
If untranslated names are guaranteed to be NULL, you can just use IFNULL(Translated.aName, Original.aName) instead.
You should probably list the actual results you want, which would help people help you in the future.
In the current case, I'm guessing you want something along these lines:
SELECT Original.id, Original.code, Translated.aName
FROM Original
JOIN Lang
ON Lang.langCode = 'DE'
JOIN Translated
ON Translated.orgId = Original.id
AND Translated.langId = Lang.id
AND Translated.aName IS NOT NULL;
(Check out my example to see if these are the results you want).
In any case, the table set you've got is heading towards a fairly standard 'translation table' setup. However, there are some basic changes I'd make.
Original
Name the table to something specific, like Animal
Don't include a 'default' translation in the table (you can use a view, if necessary).
'code' is fine, although in the case of animals, genus/species probably ought to be used
Lang
'Lanugage' is often a reserved word in RDBMSs, so the name is fine.
Specifically name which 'language code' you're using (and don't abbreviate column names). There's actually (up to) three different ISO codes possible - just grab them all.
(Also, remember that languages have language-specific names, so language also needs it's own 'translation' table)
Translated
Name the table entity-specific, like AnimalNameTranslated, or somesuch.
isTranslated is unnecessary - you can derive it from the existence of the row - don't add a row if the term isn't translated yet.
Put all 'translations' into the table, including the 'default' one. This means all your terms are in one place, so you don't have to go looking elsewhere.