MySQL combine columns from two separate and complex queries into one row - mysql

I’m working on a website where there are many distinct lines of garments. A line is defined as garments of the same design, style, manufacturer etc. Within a line, garments come in different sizes and colours.
To compose a chart of all the colours available in one particular line the following query works fine (I’m working in Coldfusion but PHP would use the same query).
SELECT
skuColourwayID,cHex,cLongName,skuID, cwColID1
from garment_sku
join garment_colourways
on cwID=skuColourwayID
join garment_colour_name
on cID=cwColID1
where skuLineID= <cfqueryPARAM value = "#url.lnID#" CFSQLType = "CF_SQL_INTEGER">
group by skuColourwayID
In order to accumulate all the info I need, I have to access three tables using joins. (I don’t have any choice about how the data is presented to me). The line is identified by lnID which in the above case starts as a url variable. Starting with the sku table (garment_sku) I access the colourways table (garment_colourways) and get the colourway colour id (cwColID1). By applying this to the colour name table (garment_colour_name) I can get the actual name of the colour, and it’s hex value.
This all works perfectly, EXCEPT a few garments come in bi-colours (ie different colour sleeves to body or collar etc). There is a second column in the garment_sku table, cwColID2 which denotes the second colour.
One way around this would be to perform two separate queries, where cwColID1 is replaced by cwColID2 in the second query. I could then combine the queries programatically to achive the bi-colour where required. However, this seems rather inelegant and I’m sure MySQL has a way of dealing with this in one query?
I hate to say it but there is also provison in the tables for a third colourway cwColID3 though I’ve never come across any three colour garments and would be very happy to solve this for just the two colours.
Thanks for any help you can give.

You just need to JOIN to the garment_colour_name table a second time to get the name of the second colour. Note that since not all garments will have 2 colours, you need to use a LEFT JOIN rather than an INNER JOIN:
SELECT
skuColourwayID,
gc1.cHex AS c1Hex,
gc1.cLongName AS c1Name,
gc2.cHex AS c2Hex,
gc2.cLongName AS c2Name,
skuID,
cwColID1,
cwColID2
from garment_sku
join garment_colourways
on cwID=skuColourwayID
join garment_colour_name gc1
on gc1.cID=cwColID1
left join garment_colour_name gc2
on gc2.cID=cwColID2
where skuLineID= <cfqueryPARAM value = "#url.lnID#" CFSQLType = "CF_SQL_INTEGER">
group by skuColourwayID

Related

SQL - How to select/delete rows with the max value depending on two others

I'm an intern in a property rental company. I'm in charge of developping the CRM under Symfony.
So, ones of my entities are properties (houses) and their availabilities. See the table structure below.
The problem I'm facing for now, is that the availabilities had been defined for each day (e.g. 28/01, 29/01, 30/01) instead of being defined for a range of day (e.g. 28/01 -> 30/01). So, the table is really heavy (~710 000 rows). Furthermore, before we changed the way of editing an availability, it created a new row for a same date instead of editing it. So, there are a lot of duplications in this table.
What I want, is to lighten the DB by keeping only the rows which have the max value in date_modif_availabilities for the same date_availabilities and id_properties.
For example, if I have these rows (availabilities_duplications):
I only want to keep the row with the latest modif like this (availabilities_keep_max_value) :
The thing is, I don't know enough the SQL language. I'm able to write few basics scripts but not complex subqueries. Even with code samples that I found.
Thank you in advance for your help.
You could select the elements for which no element with greater modified date exists.
Something like this:
SELECT avl1.*
FROM availabilities avl1
WHERE NOT EXISTS (SELECT *
FROM availabilities avl2
WHERE avl1.date_availabilities = avl2.date_availabilities
AND avl1.id_properties = avl2.id_properties
AND avl2.date_modif_availabilities > avl1.date_modif_availabilities);
This of course has the pre-condition that the combination of the three columns date_availabilities, id_properties and date_modif_availabilities is unique.
Furthermore, it seems that all columns (except the PK) may be NULL. Looks kinda odd to me.
You can use subquery :
select t.*
from table t
where id_availabilities = (select t1.id_availabilities
from table t1
where t1.id_properties = t.id_properties and
t1.date_availabilities = t.date_availabilities
order by t1.date_modif_availabilities desc
limit 1
);
However, if you have concern about the performance, then you want index on (id_properties, date_availabilities and id_availabilities).

Testing if a row exists in a table for a report

I'm trying to write a report that lists all the rows from a master table and inserts a field ("Y"/"N") if the key exists in a current-use table. For example, the COLOR_MASTER table has 256 colors by COLOR_NAME (field/key). The CURRENT_PROJECTS has a row for each project and the COLOR_NAME (field). I want to list all the COLOR_MASTER rows and then on the same print line a "Y" or "N" if that COLOR_NAME is used in the CURRENT_PROJECTS table.
I've tried to mess around with it in the Design View and have had no luck. The JOIN that was created looks basically like this and how I want the report is following the dashes:
RIGHT JOIN COLOR_MASTER ON CURRENT_PROJECTS.COLOR_NAME =
COLOR_MASTER.COLOR_NAME ON CURRENT_PROJECTS.COLOR_NAME =
COLOR_MASTER.COLOR_NAME;
--------
Color Used
BLUE
RED Y
YELLOW
I have no expertise in JOINs and I don't understand why this JOIN was created or what I need to do to fix it. Based on my reading, I guess it's trying to do an outer join.
Currently, I'm just trying to show the COLOR_NAME if used as I don't know how to test that it is used and convert it to "Y". I don't care if the color is used once or twenty times and I don't really want any data from the CURRENT_PROJECTS table.
Under the "Used" column I now have "#Error" on all lines. So, I'm figuring that the RIGHT JOIN has an error.
Any guidance is appreciated.
Thanks
I expect the RIGHT JOIN is defined in the table Relationships builder and a query using the tables adopts the established link. If you want to change the join type in a query then with query in design view, double click on the line linking tables to open the Join Properties dialog.
If there is only one record per project in Current_Projects and a color can be used only once, simply:
SELECT Color_Master.Color_Name, IIf([Current_Projects].[Color_Name] Is Null,"N","Y") AS Used
FROM Color_Master LEFT JOIN Current_Projects ON Color_Master.Color_Name = Current_Projects.Color_Name;
However, it sounds like each color can be used for multiple projects. So will need to use GROUP BY or DISTINCT query joined to the Master_Colors table:
SELECT DISTINCT Current_Projects.Color_Name FROM Current_Projects;
SELECT Color_Master.Color_Name, IIf([Query1].[Color_Name] Is Null,"N","Y") AS Used
FROM Query1 RIGHT JOIN Color_Master ON Query1.Color_Name = Color_Master.Color_Name;
Here is all-in-one SQL:
SELECT Color_Master.Color_Name, IIf([Query1].[Color_Name] Is Null,"N","Y") AS Used
FROM (SELECT DISTINCT Current_Projects.Color_Name FROM Current_Projects) AS Query1
RIGHT JOIN Color_Master ON Query1.Color_Name = Color_Master.Color_Name;
If you don't want anything displayed for the N result then use Null without quote marks in the expression.
An alternative is DLookup() but domain aggregate functions can perform slowly in query or textbox expression.
Advise not to save the calculated value to table, just calculate when needed.
You don't have to do it all in one query. Start by building a query that as the IDs of all the colors currently in use. Name it something like ColorsInUse and save it.
It could be something as simple as:
SELECT [COLOR_NAME] FROM [CURRENT_PROJECTS] GROUP BY [COLOR_NAME]
Then all you have to do is run the following queries:
UPDATE [COLOR_MASTER] SET [MyField]="N"
UPDATE [COLOR_MASTER] SET [MyField]="Y" WHERE [COLOR_NAME] IN [ColorsInUse]
Another way of doing it is by using DLookup. Something like this:
UPDATE [COLOR_MASTER] SET [MyField]=IIF(NZ(DLookup("[COLOR_NAME]","[CURRENT_PROJECTS]","[COLOR_NAME]='" & [COLOR_NAME] & "'"),"")="","N","Y")
Some notes: You should not use a text field (like a name) as your key. You should always use numerical IDs. You should also never use a text Y/N. Use an actual Yes/No field instead.

Tell from Which table MySQL COALESCE returned the value

i have the following part of query:
SUM(COALESCE(user_a, user_b)) AS income_adsense
Now, i have a html table in my web app where i present the data from this query.
problem is i want to mark data in one color if answer is from col user_a and different color if answer is from user_b col.
is there a way to achieve that in my query itself? (some sort of flag maybe?)
.
right now the only solution i have is to return all col's and work with the data on the client side but i am wondering if there's a cleaner/best practice solution.
guess it's worth mentioning i don't want to change the table structure.
Well, to make sense of the data I would do something like:
CASE
WHEN SUM(user_a) > SUM(user_b)
THEN 'User_A'
ELSE 'User_B'
END [Most of the data comes from]
You could also have two separate SUM() columns to make sense of this and compare the sum of values in your application.
SUM(user_a) [User_A Score Weight]
, SUM(user_b) [User_B Score Weight]

How to classify ranges of values in access query

Hello I am currently stuck on a problem. Any help will be appreciated. The data I am looking to classify are weights ranging from 0-80. If the line item is between 0-19 tag it as light 19-39 medium, etc... I am struggling for a starting point for how to get this to work. This query is pulling multiple fields from the data source but this is the only one that is being modified. After this the data will be re-classified based on light, medium, etc.
Thanks for the help. Let me know if anything is needed
You can make a table called WeightClasses
Then you can join to this
Select t.*, wc.weightclassname
From Things as t
inner join WeightClasses as wc
on t.Weight >= wc.LowerBound and t.Weight < wc.UpperBound
This will produce results like this
I think this is a lot easier to read and auditable than IIF statements. You can change your classifications in a table without changing code and you can make sense of your classes very quickly and easily by looking at the table. You can also add weight classes just by adding new records.
USE IIF like this:
IIF(SteelData.[Unit Weight]<19.0001,'Light',IIF(SteelData.[Unit Weight] <
39.00001,'Medium',IIF([etc.])))

MS Access Query using IFF to compare values

I am trying to build a query which will look at the data in two fields in two different tables and check to see if the data is the same, if it is I want it to return the number of times it is matched, if it isn't I simply want it to return the text saying "No viewings".
I have constructed this query in my access database which has the field from the first table "Property" and the second field I want it to compare the data with, "Viewings". I have build the following expression using the build tool, however I am stuck to make it work since every time I get this error message when trying to run the query: "Your query does not include the specified expression 'Property Viewed' as part of an aggregate function."
totalViewings: IIf([Viewings]![Property Viewed]=[Property]![ID],Count([Viewings]![Property Viewed]=[Property]![ID]),"No Viewings")
Any help how to overcome this error would be very appreciated.
Thanks
I would suggest doing something like this:
1) Assuming this is something you are developing yourself, make sure your data structure is all in order first. Since I dislike relatively code-hostile identifiers, I'd have the tables as so -
Properties - PropertyID (AutoNumber, primary key), HouseNumberOrName, Street, etc.
Viewings - ViewingID (AutoNumber, primary key), PropertyID (Number/Long Integer), ViewingDate, etc.
In the Relationships view, Properties.PropertyID would then be set up to point to Viewings.PropertyID in a one-to-many relation.
2) Your actual query I would then break into two, the first to compile the data and the second to format it for display. The first would go like this, saved as ViewingCounts...
SELECT Properties.PropertyID, Count(Viewings.PropertyID) As ViewingCount
FROM Properties LEFT JOIN Viewings ON Properties.PropertyID = Viewings.PropertyID
GROUP BY Properties.PropertyID;
... and the second like this, saved as ViewingCountsForDisplay:
SELECT Properties.*, IIf(ViewingCount = 0, 'No viewings', ViewingCount) AS Viewings
FROM Properties INNER JOIN ViewingCounts ON Properties.PropertyID = ViewingCounts.PropertyID
ORDER BY Properties.PropertyID;