Mysql Select with concat where some fields are null - mysql

I'm doing a join between two tables to push criteria values into a record description. The problem is some records do not have some/all criteria and the entire string fails:
Select Concat(Description,'<br><br>',C.CritieraNameA,': ',T.CriteriaValueA,'<br><br>',C.CriteriaNameB,': ',T.CriteriaValueB)
From Records T
Inner Join Company C
On T.CompanyID=C.ID
so I end up with
Supermarket specializing in Dairy Products
Hours: 8am-5pmCredit Cards: Yes
and
Gone with the Wind
Running Time: Too long
Format: DVD
This works fine until I hit a record where either
There is no CriteriaTypeA or CriteriaTypeB in the Company Table
There is no CriteriaValueA or CriteriaValueB in the Records Table
Is there a way to do this select so when it doesn' find a CriteriaValue in Records:
Supermarket specializing in Meats
Hours:
Credit Cards: Yes
or a CriteriaName in Company:
Porsche
Type: Sports Car
It does not simply return an empty result?

IfNull could be useful in this case - it will detect a null and replace it with a value you supply.
IFNULL(CriteriaTypeA , "not given")

Concat_WS to the rescue:
Concat_WS('',C.CriteriaTypeA,': ',T.CriteriaValue)

This should do it:
Select Concat(
Description,
Coalesce(Concat('<br><br>',C.CritieraNameA,': ',T.CriteriaValueA), ''),
Coalesce(Concat('<br><br>',C.CriteriaNameB,': ',T.CriteriaValueB), '')
)
From Records T
Inner Join Company C
On T.CompanyID=C.ID
But as I wrote in the comment: Don't implement output logic in SQL.

Related

How to do a "SELECT DISTINCT" with two "INNER JOIN"?

What I'm trying to do is to GetAPersonByID by doing some inner joins from different tables.
TABLE PEOPLE
IDPerson
Name
LastName
E-mail
fk_ID_Skin
1
Example
Explanation
help#please.com
1
2
Example2
Explanation
ineed#somebody.com
2
TABLE SKINS
IDSkin
Name
1
Normal
2
Weird
TABLE PRODUCTS
IDProduct
Name
fk_skin_type
Photo
1
Oil
1
PhotoOil
2
Water
2
PhotoWater
3
Cream
2
PhotoCream
I need to know which products the CUSTOMER should use according to their SKIN TYPE
But... When I tried to do the InnerJoins (My apologies for the Spanish text in the database):
SELECT
people.IDPerson AS 'Id_person',
people.name AS 'Name',
people.lastname AS 'Lastname',
people.email AS 'E-mail',
skins.name AS 'Skin',
products.name AS 'Product',
products.photo AS 'Photo'
FROM
((people
INNER JOIN skins
ON people.fk_ID_skin = skins.IDSkin)
INNER JOIN products
ON people.fk_ID_skin = products.fk_skin_type)
WHERE IDPerson = c_id;
How can I show 'X Person' without repeating the data?
I'm using MySQL Workbench
How can I show 'X Person' without repeating the data?
It sounds like you are saying you want to see only 1 row per person? Assuming that's the case then I think what you are looking to do is GROUP BY IDPerson. Then you could use the GROUP_CONCAT function in your SELECT statement to generate a comma separated list of the values Foto, Producto, etc.

All records not showing when using a WHERE statement with CONCAT

I have a list of plant, which can be filtered with a CONCAT, originally it was just text, but I have converted it to ID's instead. It was showing all records and could be filtered before I converted to ID's.
This involves 4 tables. (with example data) "" are not used in the fields, they are just to show you that it is a word.
plant
idplant example 1
plantname example "001 Forklift"
idplanttype1 example 1
idlocation1 example 1
iddepartment1 example 1
planttypes
idplanttype example 1
planttype example "Forklift Truck"
locations
idlocation example 1
location example "Preston"
departments
iddepartment example 1
department example "Waste Disposal"
Without the WHERE statement, it shows all records, including nulls. (but the filter doesn't work)
But With the WHERE statement, it is only showing complete records (all of which have no Null fields and the filter works) records with nulls do not show
The issue seems to be the CONCAT. (i've cleaned up the parentheses, but had to add a 1 to make the id's different)
if(isset($_POST['search'])) {$valueToSearch = $_POST['valueToSearch'];}
$sql = "
SELECT idplant, plantname, planttype, location, department
FROM plant
LEFT JOIN planttypes ON idplanttype1 = idplanttype
LEFT JOIN locations ON idlocation1 = idlocation
LEFT JOIN departments ON iddepartment1 = iddepartment
WHERE CONCAT(plantname, planttype, location, department) LIKE
'%".$valueToSearch."%'
ORDER BY plantname";
SOLUTION
The above code works, it was just missing.
WHERE CONCAT_WS
I'm new to Joins, so any help would be greatly appreciated.
Edit: Using Linux Server - Apache Version 2.4.46
Thanks in advance!
Your problem is probably blanks.
WHERE CONCAT(plantname, planttype, location, department)
LIKE '%001 Forklift Forklift Truck Preston Waste Disposal%'
won't find anything for example, as the concated strings result in '001 ForkliftForklift TruckPrestonWaste Disposal', not '001 Forklift Forklift Truck Preston Waste Disposal'.
You want blanks between the substrings, which is easiest to achieve with CONCAT_WS:
SELECT p.idplant, p.plantname, pt.planttype, l.location, d.department
FROM plant p
INNER JOIN planttypes pt ON pt.idplanttype = p.idplanttype1
INNER JOIN locations l ON l.idlocation = p.idlocation1
INNER JOIN departments d ON d.iddepartment = p.iddepartment1
WHERE CONCAT_WS(' ', p.plantname, pt.planttype, l.location, d.department)
LIKE '%001 Forklift Forklift Truck Preston Waste Disposal%'

Crosstab Query on multiple data points

I have a table that tracks employee quality assessment data. It includes the employee name, 5 yes/no fields tracking important items and the date the user did each task as column headings. Each employee gets 10 records a month so it includes a lot of data about how well our employees are doing at those 5 tasks.
I would like a report that shows me the monthly averages of these 5 yes/no fields: Appeal, NRP, Churn, Protocol, and Resub. I want those to be the Row Headers. I want the column headers to be sequential Months and the Averages to be the values. I can do this with a crosstab query for a single item such as avg:Appeal as the value and the user as the row header. How can I construct my query to use all 5 yes/no fields? They hoped for result would look like:
Table image showing how I want it to look
Comments on the Correct Answer:
June7 came up with a great answer! I changed the True to False in the DataUNION query because I wanted the Accuracy percentage and the true indicates an error on the employee evaluation. I also added in a few fields I didn't mention before. Thank you very much for helping a scrub out June7! Reading through what you wrote inspired me to start taking an SQL course on Lynda. I know its basic but you have to start somewhere and I'm getting to the point where access's builtin functions aren't doing it for me. Hopefully with the next question I'll be able to address the concerns of the commentators below that were upset that I didn't have code for myself that I had tried first.
June7's revised Code
Consider:
Query1: DataUNION
SELECT ID AS SourceID, Emp, Year([TaskDate]) AS Yr, Format([TaskDate], "mmm") AS Mo, "Appeal" AS Trend
FROM Data
WHERE Appeal=True
UNION SELECT ID, Emp, Year([TaskDate]), Format([TaskDate], "mmm"), "NRP"
FROM Data WHERE NRP = True
UNION SELECT ID, Emp, Year([TaskDate]), Format([TaskDate], "mmm"), "Churn"
FROM Data WHERE Churn = True
UNION SELECT ID, Emp, Year([TaskDate]), Format([TaskDate], "mmm"), "Protocol"
FROM Data WHERE Protocol = True
UNION SELECT ID, Emp, Year([TaskDate]), Format([TaskDate], "mmm"), "Resub"
FROM Data WHERE Resub = True;
Query2: DataCOUNT
SELECT DataUNION.Yr, DataUNION.Mo, DataUNION.Trend,
Count(DataUNION.Emp) AS CountOfEmp, Q.CntYrMo, Count([Emp])/[CntYrMo]*100 AS Pct
FROM (SELECT Year([TaskDate]) AS Yr, Format([TaskDate],"mmm") AS Mo, Count(Data.ID) AS CntYrMo
FROM Data
GROUP BY Year([TaskDate]), Format([TaskDate],"mmm")) AS Q
INNER JOIN DataUNION ON (Q.Yr = DataUNION.Yr) AND (Q.Mo = DataUNION.Mo)
GROUP BY DataUNION.Yr, DataUNION.Mo, DataUNION.Trend, Q.CntYrMo;
Query3:
TRANSFORM First(DataCount.Pct) AS FirstOfPct
SELECT DataCount.Yr, DataCount.Trend
FROM DataCount
GROUP BY DataCount.Yr, DataCount.Trend
PIVOT DataCount.Mo In ("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");

MySQL - Return null values if none

I have the following schema in MySQL (read only permissions database)
http://sqlfiddle.com/#!9/1eafc/1
As you can see there are only 5 country codes:
GB, USA, GR, ES, DE
Some months some of the records might not contain one of the countries because no record was created for this country that month.
As you can see in the sqlfiddle, GB records were only created in September.
Is there any way if there isn't any record for a country in that month, instead of not being returned, to show 0 or NULL or something?
I've tried so far different variations of ISNULL, IFNULL and COALESCE but none of them worked.
I want to return something like the following
UK 0
USA 13
GR 5
ES 12
DE 1
Any ideas?
Ok, so in lieu of a functional SQLFiddle I will make a few assumptions. The country code exists in the same table as the grouped data.
If that is the case, why not use:
select DT1.CountryCode, count(DT2.ValueForCounting) as ReturnedCount
from (
select distinct CountryCode
from DataTable ) DT1
left join DataTable DT2
on DT1.CountryCode = DT2.CountryCode
and DT2.QueryConditions = 'Stuff' -- Use the join condition instead of a where clause for anything to do with DT2
your fiddle link not loading,
but i guess my two different ideas about that,
create function and manage it using if condition.
or
create view among month, country and mapping table and put month on left join
hope it works.

MySQL Query - Find_in_set on comma separated columns

I have an issue with a Query I'm conducting to do a search on a Database of events.
The purpose is about sports and the structure is:
id_event event_sport event_city
1 10 153
2 12 270
3 09 135
The table sports is like:
sport_id sport_name
1 Basketball
and the table cities is:
city_id city_name
1 NYC
So things get complicated, because my events table is like:
id_event event_sport event_city
1 10,12 153,270
2 7,14 135,271
3 8,12 143,80
and I have a multi-input search form, so that people can search for events in their city for multiple sports or for multiple cities. I'm using Chosen
The search resultant from Chosen is, for example:
City = 153,270 (if user selected more than one city)
Sport = 12 (if user only selected one sport, can be "9,15")
So what I need is to search for multiple values on cities and sports in the same column, separated by commas, knowing that sometimes we can be searching only for one value, if user didn't input more than one.
My current query is:
SELECT * FROM events e
LEFT JOIN cities c ON e.event_city=c.city_id
LEFT JOIN sports s ON e.event_sport=s.sport_id
WHERE FIND_IN_SET('1CITY', e.event_city) AND FIND_IN_SET('1SPORT', e.event_sport)
;
Which is good to search for one city, but if the user searches for two or more, I don't have way to show it.
Can you please help me?
Thanks in advance.
When the user inputs multiple cities and/or sports, split it on commas, and then the query should look like:
SELECT * FROM events e
LEFT JOIN cities c on e.event_city = c.city_id
LEFT JOIN sports s ON e.event_sport = s.sport_id
WHERE (FIND_IN_SET('$city[0]', e.event_city) OR FIND_IN_SET('$city[1]', e.event_city) OR ...)
AND (FIND_IN_SET('$sport[0]', e.event_sport) OR FIND_IN_SET('$sport[1]', e.event_sport) OR ...)
Using PHP you can build up those OR expressions with:
$city_list = implode(' OR ', array_map(function($x) { return "FIND_IN_SET('$x', e.event_city)"; }, explode(',', $_POST['cities'])));
Do the same to make $sport_list, and then your SQL string would contain:
WHERE ($city_list) AND ($sport_list)
As you can see, this is really convoluted and inefficient, I recommend you normalize your schema as suggested in the comments.