I have the query below which looks at a table of data in which each line has an ID, date/time and key action (as well as other data). This table cannot be changed and is out of my control.
The query finds an occurrence of the Create action (which is always the first) pulls the ID and Date/Time for Creation and then pulls the Date/Time of the other key actions (Add Info, Book Appt, Accept) in one row of data:
SELECT _create.ID AS ID,
_create.`datetime` AS Create,
_inform.`datetime` AS Add_Info,
_bookap.`datetime` AS Book_Appt,
_accept.`datetime` AS Accept,
FROM table AS _create
LEFT JOIN table AS _inform ON (_create.ID = _inform.ID AND _inform.action = 'Add Info')
LEFT JOIN table AS _bookap ON (_create.ID = _bookap.ID AND _bookap.action = 'Book Appt')
LEFT JOIN table AS _accept ON (_create.ID = _accept.ID AND _accept.action = 'Accept')
WHERE _create.action="Create"
So I get something like:
ID - Create Date - Inform Date - Bookap Date - Accept Date
1234 01/02/2013 02/02/2013 09/02/2013 10/02/2013
This works well.
However if the query finds 2 events of the same type ie 'Book Appt' for the same ID, which can happen sometimes, it pulls two lines of data for that ID. So I get:
ID - Create Date - Inform Date - Bookap Date - Accept Date
1234 01/02/2013 02/02/2013 09/02/2013 10/02/2013
1234 01/02/2013 02/02/2013 15/02/2013 10/02/2013
I need it to ignore the second occurence and only return one line per ID. Or, even better return a line showing Bookap Date1 and Bookap Date2.
Any ideas?
Use GROUP BY to group the records into one row, and min() to select the earliest event date.
SELECT _create.ID AS ID,
min(_create.`datetime`) AS Create,
min(_inform.`datetime`) AS Add_Info,
min(_bookap.`datetime`) AS Book_Appt,
min(_accept.`datetime`) AS Accept,
FROM table AS _create
LEFT JOIN table AS _inform ON (_create.ID = _inform.ID AND _inform.action = 'Add Info')
LEFT JOIN table AS _bookap ON (_create.ID = _bookap.ID AND _bookap.action = 'Book Appt')
LEFT JOIN table AS _accept ON (_create.ID = _accept.ID AND _accept.action = 'Accept')
WHERE _create.action="Create"
GROUP BY _create.ID;
A quick and dirty way to show all event dates but still return one row is to use the group_concat() function instead of min() in the query above. This would put multiple datetimes into single columns which your app layer would then need to parse.
Sure, use GROUP BY _create.ID after your WHERE clause.
If you want to return multiple Book_Appt values in a single row, you can use GROUP_CONCAT like this:
SELECT _create.ID AS ID,
_create.`datetime` AS Create,
_inform.`datetime` AS Add_Info,
GROUP_CONCAT(_bookap.`datetime`) AS Book_Appt,
_accept.`datetime` AS Accept,
FROM table AS _create
LEFT JOIN table AS _inform ON (_create.ID = _inform.ID AND _inform.action = 'Add Info')
LEFT JOIN table AS _bookap ON (_create.ID = _bookap.ID AND _bookap.action = 'Book Appt')
LEFT JOIN table AS _accept ON (_create.ID = _accept.ID AND _accept.action = 'Accept')
WHERE _create.action="Create"
GROUP BY `ID`
This would return a comma-seperated list of datetime values in your case.
So your output might look like
ID - Create Date - Inform Date - Bookap Date - Accept Date
1234 01/02/2013 02/02/2013 09/02/2013,15/02/2013 10/02/2013
For your first question (to return only one row) I would use an ORDER BY clause to sort your result set, followed by a LIMIT 1 expression to only return one row.
Related
My Platform is MySql
I have two queries that I need to combine, using the first query as a type of filter for the second query.
Query 1:
SELECT * FROM INVENTORY
WHERE INV_ID = 1
AND FSCL_YR = 2017
From this query we will get results back that includes a column named STR_NBR.
Which we then want to use in the second query as 'If the store number appears in the first query, give me the results where it shows in the second'. The second query tables use the column name SND_LOC_NBR instead of STR_NBR.
Query 2:
SELECT * FROM Transfer A
LEFT JOIN Transfer_Detail B
ON A.XFER_NBR = B.XFER_NBR
WHERE A.XFER_NBR = B.XFER_NBR
AND A.XFER_STAT_IND IN ('S','C')
AND (where the SND_LOC_NBR needs to match STR_NBRs found from Query 1)
Try this:
SELECT * FROM Transfer A
LEFT JOIN Transfer_Detail B
ON A.XFER_NBR = B.XFER_NBR
WHERE A.XFER_STAT_IND IN ('S','C')
AND SND_LOC_NBR IN
(SELECT STR_NBR FROM INVENTORY
WHERE INV_ID = 1 AND FSCL_YR = 2017 )
I am working on a query for a datatable and I can't seem to get it to display how I want, I don't know if this is even possible in SQL What I am looking to do is get a query to respond with ideally an extra column of Boolean type.
Currently I can run two queries and they both work perfectly but I can't work out how to join them together bellow is the code from my first query what this does is return beers a user has tried this works fine and as expected and returns as expected.
SELECT *
FROM keg.beer
JOIN keg.userbeer
ON beer.id = userbeer.beer_id
WHERE userbeer.username_id = 1;
The second query is even simpler and is just a select getting the list of beers.
SELECT * FROM keg.beer
What I want to do is run a query and have it return a list of beers with a Boolean value if the user has tried it or not.
You're not going to run into too many scenarios for "Desired Results" that can't be produced with plain 'ol SQL. In this case you'll use a CASE statement to determine if the person has tried a beer. You'll also want a LEFT OUTER JOIN so you don't drop records coming from your beer table when your filtered userid doesn't have a userbeer record for that beer:
SELECT
beer.name,
beer.id,
beer.country,
CASE WHEN userbeer.username_id IS NULL THEN 0 ELSE 1 END AS user_tried_beer_boolean
FROM keg.beer
LEFT OUTER JOIN keg.userbeer
ON beer.id = userbeer.beer_id
AND userbeer.username_id = 1;
As #SeanLange mentioned in the comments here, the restriction of the WHERE statement for the userid would cause records to be dropped that you want in your result set, so we move the restriction of username_id = 1 to the ON portion of the LEFT OUTER JOIN so that the userbeer table results are restricted to just that user before it's joined to the beer table.
Now I need a drink.
SELECT b.id,
b.name,
CASE WHEN u.username_id IS NOT NULL THEN TRUE ELSE FALSE END AS userdrankbeer
FROM keg.beer b
LEFT JOIN ( SELECT * FROM keg.userbeer WHERE username_id = 1 ) u
ON beer.id = userbeer.beer_id
;
We have two tables in mysql database.Screenshots are attached below.
Given table ads_testTable
here is the screenshot of my dimesnionvalue_flattable
We have to run a query like the one below.
SELECT Quiz_Attempt.L1_Key dimID,
Quiz_Attempt.L1_Label CatVars,
COALESCE(**xyz**,0) AS series0
FROM DSQ_ADSSCHEMA.ADS_TestTable dataTable
RIGHT OUTER JOIN LS_CONFIG.DSQ_DIMENSIONVALUES_FLAT Quiz_Attempt on dataTable.Quiz_Attempt = Quiz_Attempt.L1_Key
WHERE Quiz_Attempt.L0_Key = 'All Levels' AND
Quiz_Attempt.DimensionID = 'Packet'
GROUP BY Quiz_Attempt.L1_Key, Quiz_Attempt.L1_Label;
My motive is to write a query in place of xyz so that I can get avg of obtainedMarks column in testtable according to the value of dimID I get.Each distinct Quiz_Attempt is a different test so If a Packet is repeating for a particular Quiz_Attempt in testTable, it should take only one value for that AttemptID.
I think you query could take the form of:
SELECT
L1_Key dimID,
L1_Label CatVars,
COALESCE('**xyz**',0) AS series0
FROM (
SELECT *
FROM (SELECT * FROM ADS_TestTable GROUP BY ADS_TestTable.Quiz_Attempt) dataTable
RIGHT OUTER JOIN DSQ_DIMENSIONVALUES_FLAT Quiz_Attempt on dataTable.Quiz_Attempt = Quiz_Attempt.L1_Key
WHERE Quiz_Attempt.L0_Key = 'All Levels' AND
Quiz_Attempt.DimensionID = 'Packet'
GROUP BY dataTable.Quiz_Attempt
) A GROUP BY dimID, CatVars;
The JOIN is done in an inner query, and grouped by Quiz_Attempt, so that you get a single row per attempt. This result is then used to compute what you need.
i am trying to make a view in MS SQL having join of two table and an individual field.
i have done the joining part but now i want to add a new field in this view which is not in any of the table which is joined.
so anybody have any idea how i can create this new field in the view.
In case you want a default value for all your rows in the ACTIVE field, try this
CREATE VIEW Slots AS
SELECT Event.EventId,
Event.eventName,
examCenter.centerId,
examCenter.centerName,
slotTime.slotTimeId,
slotTime.FromTime,
slotTime.ToTime,
slotTime.Dated,
examCenter.noOfSeats,
CAST(1 AS bit) AS Active
FROM examCenter
INNER JOIN Event
ON examCenter.eventId = Event.EventId
INNER JOIN slotTime ON Event.EventId = slotTime.eventId
If the value for the ACTIVE field depends on some condition, say
slottime.Dated => getdate()
then, you will need to replace
CAST(1 AS bit) AS Active
in the above code, with
CAST(CASE WHEN slottime.Dated => getdate() THEN 1 ELSE 0 AS bit) AS ACTIVE
You can explicitly name each field if you need, aliasing them with AS as required. For example:
SELECT si.field1 as si_field1,
si.field2 as si_field2,
ind_data.field1 as ind_data_field1
FROM sites_indexed as si
LEFT JOIN individual_data as ind_data
ON si.id = ind_data.site_id
And then you can reference the aliased names in your result set.
OK I have 2 tables:
holdings: (id, long_name, value, date, sedol)
asset_key: (id, long_name, sedol)
My issue is that in holdings there are many records where the sedol wasn't filled in. I have the asset_key table however that maps a given long_name to a sedol.
Is there a query that can populate holdings.sedol with the result from asset_key?
Something like:
UPDATE holdings SET holdings.sedol =
SELECT asset_key.sedol FROM asset_key
WHERE sedol.long_name = asset_key.long_name
This will do the trick:
UPDATE
holdings
LEFT JOIN asset_key ON sedol.long_name = asset_key.long_name
SET
holdings.sedol=asset_key.sedol
This should work:
UPDATE `holdings`
SET `holdings`.`sedol` = (SELECT `asset_key`.`sedol`
FROM `asset_key`
WHERE `asset_key`.`long_name` = `holdings`.`long_name`)
However, if I am not wrong, you should be sure that this SELECT subquery returns only one row or MySQL will throw an error.
Try the below Query:
update holdings
SET holdings.sedol = asset_key.sedol
from holdings
inner join asset_key on sedol.long_name = asset_key.long_name
Note: The inner join should result in single value only