I created a VIEW using this code:
CREATE OR REPLACE VIEW aaa AS
SELECT pry.uid,
treg.nombre_es as region,
tpais.nombre_es as pais,
tdep.departamento,
dep_other, tciu.ciudad,
ciu_other
FROM tx_oriproyectos_proyectos AS pry
LEFT JOIN tx_oritablascomunes_regiones as treg ON pry.region = treg.uid
LEFT JOIN tx_oritablascomunes_paises as tpais ON pry.pais = tpais.uid
LEFT JOIN tx_oritablascomunes_departamentos as tdep ON pry.departamento = tdep.uid
LEFT JOIN tx_oritablascomunes_ciudades as tciu ON pry.ciudad = tciu.uid
And I obtained this and is Ok:
result http://finewebdesigns.com/images/mysql_view_result.jpg
And now I need to obtain concatenate results like this:
concatenated_field
---------------------------------------
Africa - ALbania - Tirana1 - Tirana2
Africa - Colombia - Guaviare - Calamar
How can I do that?
I tried this:
CREATE OR REPLACE VIEW aaa AS
SELECT CONCAT_WS (' - ', pry.uid, treg.nombre_es as region, tpais.nombre_es as pais, tdep.departamento, dep_other, tciu.ciudad, ciu_other)
FROM tx_oriproyectos_proyectos AS pry
LEFT JOIN tx_oritablascomunes_regiones as treg
ON pry.region=treg.uid
LEFT JOIN tx_oritablascomunes_paises as tpais
ON pry.pais=tpais.uid
LEFT JOIN tx_oritablascomunes_departamentos as tdep
ON pry.departamento=tdep.uid
LEFT JOIN tx_oritablascomunes_ciudades as tciu
ON pry.ciudad=tciu.uid
But I obtained:
#1583 - Incorrect parameters in the call to native function 'CONCAT_WS'
Ok, Thanks to #Mat I finally get this code, that is the expected solution to this problem.
CREATE OR REPLACE VIEW aaa AS
SELECT pry.uid, CONCAT_WS (' - ', treg.nombre_es, tpais.nombre_es, tdep.departamento, NULLIF(dep_other,''), tciu.ciudad, NULLIF(ciu_other,''))
FROM tx_oriproyectos_proyectos AS pry
LEFT JOIN tx_oritablascomunes_regiones as treg
ON pry.region=treg.uid
LEFT JOIN tx_oritablascomunes_paises as tpais
ON pry.pais=tpais.uid
LEFT JOIN tx_oritablascomunes_departamentos as tdep
ON pry.departamento=tdep.uid
LEFT JOIN tx_oritablascomunes_ciudades as tciu
ON pry.ciudad=tciu.uid
That obtains this: http://finewebdesigns.com/images/mysql_view_result_solved.jpg
You should be able to use the CONCAT_WS string function.
SELECT CONCAT_WS(' - ', treg.nombre_es, tpais.nombre_es, ...) FROM ...
From the docs:
CONCAT_WS() does not skip empty strings. However, it does skip any NULL values after the separator argument.
so your null values will simply be ignored.
If you also want to skip empty strings, you can use throw the NULLIF function in the mix, as suggested by ypercube:
SELECT CONCAT_WS(' - ', NULLIF(col,''), ...) ...
Related
I'm attempting to create additional columns for when a drive record has multiple other records assigned to the drive. In my attached screenshot, you can see there are three drives where all data is constant, but each has multiple incentives assigned to the drive.
Would a PIVOT function work to create an additional column for the incentive? I'm not looking for something dynamic and I would be OK with hard coding at the most 4 additional columns to have space for five incentives assigned to one drive.
What I would like my results to look like would be:
The last column is how I performed used For XML Path to accomplish it, but it's not exactly what I was looking for.
Here is my SQL statement:
Select
DM.DriveID [DriveID],
DM.FromDateTime [FromDateTime],
Case When DM.OwnerType = 0 Then Acct.Name Else CD.DescLong End As [OwnerName],
Acct.AccountID [AcctID],
Inc.Description [Incentive],
Stuff ((Select ', ' + isnull(EM.Description,'')
From Production.[dbo].EquipmentMaster EM
Inner Join Production.[dbo].EquipmentDetail ED On EM.EquipmentID = ED.EquipmentID And EM.EquipmentType=3
Where ED.DriveID = DM.DriveID
For XML PATH(''), TYPE).value('.', 'varchar(max)')
,1, 2, '') as [XML_Incentives]
From
Production.[dbo].rpt_DriveMaster DM
Left Outer Join Production.[dbo].rpt_Accounts Acct on DM.AccountID=Acct.AccountID
Inner Join Production.[dbo].rpt_CenterDetail CD on DM.CenterID=CD.CenterID
Left Outer Join Production.[dbo].OBI_Incentives Inc on DM.DriveID=Inc.DriveID
Where
DM.DriveID in (658946,597611,651136)
I'm looking at the link provided when marked as duplicate, but is almost like reading Greek to me. I'm trying to modify my SQL to use this as a basis, but not having much luck:
Any chance on some guidance on how this works?
Select
*
From
( Select
DM.DriveID [DriveID],
DM.FromDateTime [FromDateTime],
Case When DM.OwnerType = 0 Then Acct.Name Else CD.DescLong End As [OwnerName],
Acct.AccountID [AcctID],
Inc.Description [Incentive1],
null [Incentive2],
null [Incentive3],
null [Incentive4],
null [Incentive5]
From
Production.[dbo].rpt_DriveMaster DM
Left Outer Join Production.[dbo].rpt_Accounts Acct on DM.AccountID=Acct.AccountID
Inner Join Production.[dbo].rpt_CenterDetail CD on DM.CenterID=CD.CenterID
Left Outer Join Production.[dbo].OBI_Incentives Inc on DM.DriveID=Inc.DriveID
Where
DM.DriveID in (658946,597611,651136)
) as P
Pivot (
min(P.[Incentive])
for P.[DriveID] in ([Incentive1], [Incentive2], [Incentive3])
) as PIV
My Query looks like
$search_query = db_query("SELECT nd.nid, users.name, nd.type FROM node as nd
LEFT JOIN node_revisions as nd_rev ON nd_rev.nid = nd.nid AND nd_rev.vid = nd.vid
LEFT JOIN users ON nd.uid = users.uid
WHERE nd.status = 1 AND nd_rev.body LIKE LOWER('%node/100%')
AND nd.nid NOT IN(SELECT DISTINCT nid FROM term_node WHERE tid = 293)");
This query actually returns all the matches from node_revisions.body field, Which includes
node/1000, node/1001.... Etc.,
I want to get only the result of exact match where possible like
"node/100"
"node/100/"
"/node/100"
"/node/100/"
'node/100'
'node/100/'
'/node/100'
'/node/100/'
and not like
"node/1006"
"node/10064/"
"/node/1000"
"/node/10001/"
'node/10023'
'node/1005/'
'/node/1001'
'/node/10069/'
This above query returned me result which has string like below..
..a href="/node/1006"
How to avoid this kind of errors? Please help..
Try removing the % after 100 so the search won't consider any digit after 100, like this:
LOWER('%node/100')
Then consider the following Regular Expression
Example:
`nd_rev.body` REGEXP "^/?node/100/?$"
Oh ya... I got an resolution for this.. I redefined my query like below and it gives me result as expected..
$search_query = db_query("SELECT nd.nid, users.name, nd.type FROM node as nd
LEFT JOIN node_revisions as nd_rev ON nd_rev.nid = nd.nid AND nd_rev.vid = nd.vid
LEFT JOIN users ON nd.uid = users.uid
WHERE nd.status = 1 AND nd_rev.body RLIKE '[[:<:]]" . $search_string . "[[:>:]]'
AND nd.nid NOT IN(SELECT DISTINCT nid FROM term_node WHERE tid = 293)");
Look at
nd_rev.body RLIKE '[[:<:]]" . $search_string . "[[:>:]]'
This is what i expected
If anyone can help me rewrite my query to work in mysql 5 I would be very grateful. If anyone can provide links to solid, simple tutorials on how to rewrite old queries that would also be great.
My current (version 4) query looks like this:
SELECT
course.course_code,
course.course_title_sv AS course_title,
course.course_u_credits,
course.course_successive_level_scb_id,
s.successive_level_scb_order,
s.successive_level_scb_code,
LEFT (education_level.edu_level_name_sv, 1) AS course_edu_level, course.course_level,
GROUP_CONCAT(DISTINCT h.head_area_hv_title_sv SEPARATOR ', ') AS head_area_hv
FROM
course, course_event, course_event_package_links, package, education_level
LEFT JOIN
course_has_head_area_hv ON(course.course_id = course_has_head_area_hv.course_id)
LEFT JOIN
head_area_hv h ON(h.head_area_hv_id = course_has_head_area_hv.head_area_hv_id)
LEFT JOIN
successive_level_scb s ON(s.successive_level_scb_id = course.course_successive_level_scb_id)
WHERE
course.course_edu_level=education_level.edu_level_id AND
course.course_id=course_event.course_id AND
course_event.course_event_id=course_event_package_links.course_event_id AND
course_event_package_links.package_id=package.package_id AND
course.course_successive_level_scb_id != '' AND
package.package_id='6318'
GROUP BY course.course_id
Simply replace
SELECT ...
FROM course, course_event, course_event_package_links
...
WHERE course.course_id=course_event.course_id
AND course_event.course_event_id=course_event_package_links.course_event_id
by
SELECT ...
FROM course
JOIN course_event ON course_event.course_id = course.course_id
JOIN course_event_package_links
ON course_event_package_links.course_event_id = course_event.course_event_id
...
About your error message, are you sure course.course_id exists? Maybe it was replaced by course.course_code?
I am trying to use the following query in SQL Server
SELECT [AL].[Subscriptions].Id,
[AL].[Subscriptions].name,
[AL].[Subscriptions].description,
[AL].[Subscriptions].price,
[AL].[Subscriptions].iconFileName,
IIf(a.expiryDate > Now(), 'TRUE', 'FALSE') AS isSubsByUser
FROM [AL].[Subscriptions]
LEFT JOIN (SELECT *
FROM [AL].[UserSubscriptions]
WHERE userId = 13259) AS a
ON Subscriptions.Id = a.itemid;
but always get the error
Error in list of function arguments: '>' not recognized.
Unable to parse query text.
How do I resolve it?
Like Martin Smith said you need to use a case statement. Also it looks like you are only using a couple of fields in the derived table therefor I would suggest not using *. I put a example below.
SELECT [AL].[Subscriptions].Id,
[AL].[Subscriptions].name,
[AL].[Subscriptions].description,
[AL].[Subscriptions].price,
[AL].[Subscriptions].iconFileName,
case when a.expiryDate > GetDate() then 'TRUE' else 'FALSE' end AS isSubsByUser
FROM [AL].[Subscriptions]
LEFT JOIN (SELECT expiryDate, itemid
FROM [AL].[UserSubscriptions]
WHERE userId = 13259) AS a
ON Subscriptions.Id = a.itemid;
I have relationships that might not necessarily exist (they could be optional i.e. null); for example, a image may not have an address so it may be null.
I am unsure how to not return all null values.
Is there some condition I can put in place on the join that says if the address is null don't do a join and don't return all the null columns?
SELECT im.title, im.alias_title, im.description, im.main_image, im.hits,
im.show_comment, im.created_on, im.date_taken, im.account_type_id,
c.make, c.model, ad.address_line_1, ad.address_line_2,
spc.state_province_county, tvc.town_village_city, co.country,
ge.latitude, ge.longitude, ge.zoom, ge.yaw, ge.pitch,
us.first_name, us.surname, us.user_set_online, ut.username,
ut.account_type_id, aty.`type`, ufy.realname, ufy.location,
ufy.location, ufy.account_type_id
FROM image im
INNER JOIN user us
ON im.user_id = us.id
LEFT JOIN user_type ut
ON us.id = ut.user_id
LEFT JOIN user_flickr_youtube ufy
ON ut.id = ufy.user_type_id
LEFT JOIN account_type aty
ON ut.account_type_id =aty.id
LEFT JOIN address ad
ON im.address_id = ad.id
LEFT JOIN state_province_county spc
ON ad.state_province_county_id = spc.id
LEFT JOIN town_village_city tvc
ON ad.town_village_city_id =tvc.id
LEFT JOIN country co
ON ad.country_id =co.id
LEFT JOIN geolocation ge
ON im.geolocation_id = ge.id
LEFT JOIN camera c
ON im.camera_id = c.id
WHERE im.alias_title = 'test'
AND im.approved = 'Yes'
AND im.visible = '1'
LIMIT 1;
Is there some condition i can put in place on the join that says if the address is null dont do a join and dont bring me back all the null columns
Yes; you can run a JOIN instead of a LEFT JOIN. But that won't simply exclude the address if it is NULL, it will ignore the whole row altogether.
Usually this kind of situation is either handled by supplying a default value, possibly empty, for example directly in MySQL
SELECT
...COALESCE(ad.address_line_1,'(no address)') AS address_line_1,
COALESCE(ad.address_line_2,'') AS address_line_2, ...
or it is handled by the application:
if row['address_line_1']:
result = result + ("<td class=\"address\">%s</td>" % ( row['address_line_1'] ))
...
This also because a query could potentially return not one record, but several, and of these, some might have a NULL colum and some might not.
UPDATE
There is a way, but it's likely to make milk go sour in cows fifty miles downrange.
This is a proof of concept, on a MUCH smaller query and table, and takes advantage of the possibility of dynamically building a query.
First of all we have our query WHERE condition, here represented by "id = 1". We want to have the name column if the name column is not NULL.
SELECT #address := COALESCE(MIN(',name'),'') FROM client WHERE name IS NOT NULL AND id = 1;
This will return an empty string if the selected column is NULL. Otherwise it will return a comma and the name of that column.
This is the statement that in your case will be humongous, given your query. It contains the same WHERE as before, without the request that the name be NULL. And the field list is now dynamic.
SELECT #string := CONCAT('SELECT id', #address, ' FROM client WHERE id = 1');
Except that #string is, well, a string. To execute it as a query we do
PREPARE query FROM #string;
EXECUTE query;
DEALLOCATE PREPARE query;
How this might interact with your application, I do not dare fathom. I have tried an implementation in PHP on an expendable VM :-), cycling between the values of 1 and 3 (one row has a NULL name, one hasn't).
<?php
// Connect to this VM's local DB
mysql_connect('localhost','root','') or die("Cannot connect");
mysql_select_db('test');
foreach(array(1, 3) as $id)
{
mysql_query("SELECT #address := COALESCE(MIN(',name'),'') FROM client WHERE name IS NOT NULL AND id = $id;");
mysql_query("SELECT #string := CONCAT('SELECT id', #address, ' FROM client WHERE id = ', $id);");
mysql_query("PREPARE query FROM #string;");
$exec = mysql_query("EXECUTE query;");
while($tuple = mysql_fetch_assoc($exec))
{
print implode(" | ", $tuple) . "\n";
}
mysql_query("DEALLOCATE PREPARE query;");
}
?>
The answer seems to indicate it's working:
1 | Rossi
3
(I wouldn't have been surprised if it returned something like 'Ia! Cthulhu fhtagn!').