I know this row concatenation question has been asked before but I cannot find answers that will solve my problem. I have an older AS400/DB2 database that I am using an Excel ODBC connector to get to the data. I have used MySQL in the past but this is my firstt attempt at MSSQL. To set up the question I have the following:
A work order number (wono)
A note line number (ntlno1)
A note data 50 character text length (ntda)
For each wono you can have several line numbers (ntlno1) and each line number can have up to 50 characters of data (ntda). I need to be able to concatenate all of the ntda data into one field by work order number and note line number. Here is what I have so far:
SELECT
DISTINCT WOHDR.wono AS WONO, WONOT.ntlno1 AS NoteLineNo, substring((Select ','+WONOT.ntda AS [text()]
From libd09.wopnote0 WONOT
Where WONOT.wono = WOHDR.wono
ORDER BY WONOT.wono
For XML PATH ('')),2, 1000) [wopnote0]
FROM libd09.wophdrs0 WOHDR
LEFT JOIN libd09.wopsegs0 WOSEG ON (WOHDR.wono = WOSEG.wono)
LEFT JOIN libd09.cslusrp0 USR ON (WOSEG.clsdby = USR.uspfid)
LEFT JOIN libd09.woplabr0 WOLBR ON (WOHDR.wono = WOLBR.wono)
LEFT JOIN libd09.wopnote0 WONOT ON (WOHDR.wono = WONOT.wono)
LEFT JOIN libd09.wopmisc0 WOMISC ON (WOHDR.wono = WOMISC.wono)
LEFT JOIN libd09.wopempf0 WOEMP ON (WOMISC.epidno = WOEMP.epidno)
LEFT JOIN libd09.woppart0 WOPART ON (WOHDR.wono = WOPART.wono)
LEFT JOIN tafilev22.employ01 TAEMP ON (WOMISC.epidno = TAEMP.ememp)
WHERE WOHDR.opndt8 BETWEEN ? AND ?
I have only included the pertinent columns though the joins have all the tables that I need. when I run the query I get the following error: Token [ was not valid. Valid tokens: .
I am sure I am missing something simple so any advice or help would be greatly appreciated.
Related
Hopefully i can explain this well enough. I have a bit of a unique issue where the customer system we use can change a ID in the database in the background based on the products status.
What this means is when i want to report old products we don't use anymore along side active products there ID differs between the two key tables depending on there status. This means Active products in the product table match that of the stock item table with both showing as 647107376 but when the product is no long active the StockItem table will present as 647107376 but the table that holds the product information the id presents as -647107376
This is proving problematic for me when i comes to joining the tables together to get the information needed. Originally i had my query set up like this:
SELECT
Company_0.CoaCompanyName
,SopProduct_0.SopStiStockItemCode AS hbpref
,SopProduct_0.SopStiCustomerStockCode AS itemref
,SopProduct_0.SopDescription AS ldesc
,StockMovement_0.StmOriginatingEntityID AS Goodsin
FROM
SBS.PUB.StockItem StockItem_0
LEFT JOIN SBS.PUB.SopProduct SopProduct_0 ON StockItem_0.StockItemID = SopProduct_0.StockItemID
LEFT JOIN SBS.PUB.Company Company_0 ON SopProduct_0.CompanyID = Company_0.CompanyID
LEFT JOIN SBS.PUB.StockMovement StockMovement_0 ON StockItem_0.StockItemID = StockMovement_0.StockItemID
WHERE
Company_0.CoaCompanyName = ?
AND StockMovement_0.MovementTypeID = '173355'
AND StockMovement_0.StmMovementDate >= ? AND StockMovement_0.StmMovementDate <= ?
AND StockMovement_0.StmQty <> 0
AND StockMovement_0.StockTypeID ='12049886'
Unfortunately though what this means is any of the old product will not show because there is no matching id due to the SopProduct table presenting the StockItemID with a leading -
So from this i thought best to use a case when statement with a nested concat and left in it to bring through the results but this doesn't appear to work either sample of the join below:
LEFT JOIN SBS.PUB.SopProduct SopProduct_0 ON (CASE WHEN LEFT(SopProduct_0.StockItemID,1) = "-" THEN CONCAT("-",StockItem_0.StockItemID) ELSE StockItem_0.StockItemID END) = SopProduct_0.StockItemID
Can anyone else think of a way around this issue? I am working with a Progress OpenEdge ODBC.
Numbers look like numbers. If they are, you can use abs():
ON StockItem_0.StockItemID = ABS(SopProduct_0.StockItemID)
Otherwise a relatively simple method is:
ON StockItem_0.StockItemID IN (SopProduct_0.StockItemID, CONCAT('-', SopProduct_0.StockItemID))
Note that non-equality conditions often slow down JOIN operations.
Using an or in the join should work:
LEFT JOIN SBS.PUB.SopProduct SopProduct_0
ON SopProduct_0.StockItemID = StockItem_0.StockItemID
OR
SopProduct_0.StockItemID = CONCAT("-", StockItem_0.StockItemID)
You might need to cast the result of the concat to a number (if the ids are stored as numbers).
Or you could use the abs function too (assuming the ids are numbers):
LEFT JOIN SBS.PUB.SopProduct SopProduct_0
ON SopProduct_0.StockItemID = abs(StockItem_0.StockItemID)
SELECT
TC_TXN.BOOKING_REF_ID,
TC_TXN.CREATION_TIME,
IFNULL(MAN_REQ.SUB_COMPANY_CODE,"") AS "SUB_COMPANY_CODE",
IFNULL(CONCAT(' / ',SUBSTRING_INDEX(SUB_COMP.BV_GROUP_FQN_NAME,'/',-1)),"") AS SUB_COMPANY_NAME,
"Company" AS "BILL_TO",
"" AS "REF",
BV_ENUM.VALUE,
MI_TXN.PRODUCT_CHARGES,
IFNULL(TC_TXN.VENDOR_PAYABLE_AMOUNT,0) AS VENDOR_AMOUNT,
IFNULL(MAN_REQ.TICKET_NO,(select TICKET_NO from TC_FLIGHTS_BOOK tfb join TC_TRANSACTION tcx on(tcx.TRANSACTION_ID=tfb.TRANSACTION_ID) join TC_FB_FARE_DETAILS tf on (tf.OID=tfb.OID) limit 1)) AS "TICKET_NO",
IFNULL(TC_FB.SP_PNR_NO,IFNULL(MAN_REQ.PNR_NO,"")) AS "PNR_NO",
MAN_REQ.TOUR_CODE,
TC_TXN.TRANSACTION_ID,
TC_TXN.REQUEST_ID,
MAN_REQ.EMPLOYE_ID,
"" AS "TCID"
FROm TC_TRANSACTION TC_TXN
LEFT JOIN MANUAL_INVOICE_TRANSACTION MI_TXN ON (TC_TXN.TRANSACTION_ID = MI_TXN.TRANSACTION_ID)
LEFT JOIN MANUAL_INVOICE_REQUEST MAN_REQ ON (MAN_REQ.REQUEST_ID = MI_TXN.REQUEST_ID)
LEFT JOIN TCP_ORGANIZATION SUB_COMP ON (SUB_COMP.ORGANIZATION_ID = TC_TXN.CUSTOMER_CODE)
LEFT JOIN BV_ENUM_VALUES BV_ENUM ON (TC_TXN.BOOKING_TYPE = BV_ENUM.INT_CODE AND BV_ENUM.TYPE_NAME = 'BOOKING_TYPE')
LEFT JOIN TC_FB_FLIGHT_DETAILS TC_FB ON (TC_FB.OID=TC_TXN.OID)
WHERE
TC_TXN.CREATION_TIME>=? and TC_TXN.CREATION_TIME<= ? AND TC_TXN.CURRENT_BOOKING_STATUS=0
GROUP BY TC_TXN.TRANSACTION_ID
when I am running this query for ticket_no column only 1st data is fetched. Remaining columns are fetching properly. i am using trying to solve this error for more than 2 days.
Thanks in advance
In the light of the comment by the OP ("for every row the ticket_no value is same"), the issue is that the subquery for the ticket_no field is not a correlated one. This means that its value does not depend on any value from the outer query:
...
IFNULL(MAN_REQ.TICKET_NO,(select TICKET_NO from TC_FLIGHTS_BOOK tfb join TC_TRANSACTION tcx on(tcx.TRANSACTION_ID=tfb.TRANSACTION_ID) join TC_FB_FARE_DETAILS tf on (tf.OID=tfb.OID) limit 1)) AS "TICKET_NO",
...
This also means that MAN_REQ.TICKET_NO field is always null, which begs the question why it is there in the first place.
Since the issue is with the data and the question does not describe how the tables are related, nor provides any sample data, I cannot provide an exact solution, only point out the root cause.
I have a rather big SQL statement that I am working with in MS Access 2010. Here it goes:
SELECT
W.ID AS wid,
W.wpt_ty AS ty,
W.wpt_num AS num,
W.wpt_nxt AS nxt,
W.latdeg AS lat,
W.londeg AS lon,
W.alt AS alt,
W.mission_id AS mid,
W.ctg1 AS ctg1,
W.ctg2 AS ctg2,
W.ctg3 AS ctg3,
W.ctg4 AS ctg4,
W.wpt_index AS indx,
W.vel AS vel,
W.tu AS tu,
R.route_num AS rnum,
R.AC_num AS ac,
R.route_type AS rtype,
R.LastUpdatedOn AS d8,
R.LastUpdatedBy AS auth,
R.flight_wpt_count AS wfcount,
M.mission_name AS msnName,
V.Description AS vstatus,
R.disallowed_reason_id AS did,
CW.wpt_num AS c1num,
CR.matching_route_id AS c1mrid,
CW.wpt_index AS c1indx,
CRU.runway_name AS c1rnwy,
CR.route_num AS c1rnum
FROM Validation AS V
(RIGHT JOIN Runways AS CRU
INNER JOIN (Routes CR
INNER JOIN Waypoints CW ON CR.ID = CW.route_id)
ON Runways.ID = Routes.runway_id
INNER JOIN ((Missions as M
INNER JOIN Routes AS R ON M.ID = R.mission_id)
INNER JOIN Waypoints AS W ON (R.ID = W.route_id)
AND (M.ID = W.mission_id)) ON
V.ID = R.validated
WHERE (((R.matching_route_id)=307543) AND ((R.validated) <> 0 ))
AND (((CW.mission_id)=mid) AND ((CW.wpt_num) = (ctg1))))
If you look at the bottom, you can see am I referencing the values ctg1 and mid on a Right Join while the Inner Joins reference other literal values. Eventually I will want to do the same for ctg2, ctg3, and ctg4
Right now I am running these as 2 separate queries but finding it to be way too slow. If I can join combine the queries (sort of like how I am showing here) it could speed things up greatly. But I am at a loss for how to:
Using select values earlier in said query from the Inner/Left join and push them into values needed on the Right join.
I may be using joins incorrectly, but I thought they had to do with combining data from possible the same tables, just on different pivot points.
How to use the MS Access GUI to help write a query like this.
I know this is for MS Access but I am tagging for MySQL just in case there are similar queries there which can be ported to MS Access?
Have you tried using UNION for this?
It would allow you to execute this query (As two queries, which you mentioned as a possibility), and join the results for your output.
Be warned, it will eat up (only show one of) your duplicates in the results set.
I also suggest reading up on the different types of joins for your own benefit, in the following answer:
MYSQL Joins
I currently have a search form which should allow a user to search for a customers full name and it will return the row.
For Example: A user searches for "Mr. N Mallow" and it will return the row which matches that query. Since I am new to MySQL I need some help, I've tried + but that has no effect, probably because it's not standard mysql or something like that.
select *
from mooring
left join customer
on mooring.assignedTo = customer.id
where mooring.Number like \"$var\"
or (customer.TitleName + customer.Surname = '$var')
Any suggestions?
select * from mooring
left join customer on mooring.assignedTo = customer.id
where mooring.Number like \"$var\" OR (customer.TitleName + customer.Surname = '$var')
Try CONCAT_WS or CONCAT, which join strings together (the first version is "with separator"):
CONCAT(customer.TitleName,' ',customer.Surname)
or
CONCAT_WS(' ',customer.TitleName,customer.Surname)
I am currently running this SQL
SELECT jm_recipe.name, jm_recipe.slug
FROM jm_recipe
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
This returns the desired results except that I also need to return the name of the category that the recipe I am looking for is in, to do this I tried to add the field in to my SELECT statement and also add the table into the FROM clause,
SELECT jm_recipe.name, jm_recipe.slug, jm_category_name
FROM jm_recipe, jm_category
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
However this just returns no results, what am i doing wrong?
You need to join both tables:
SELECT jm_recipe.name, jm_recipe.slug, jm.category_name
FROM jm_recipe
INNER JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
INNER JOIN jm_category ON jm_recipe.recipe_id = jm_category.recipe_id
WHERE jm_category_recipe.category_id = $cat
I've changed the joins to inner joins as well. You might want to make them both LEFT joins if you have NULLs and want them in the result.
Also, you're vulnerable to SQL Injection by simply copying over $cat.
Here's some PHP specific info for you (I'm assuming you're using PHP.)