Joining 2 row of data into 1 row of data - mysql

I have a table which looks like this
|Application No | Status | Amount | Type |
==========================================
|90909090 | Null | 3,000 | Null |
|90909090 | Forfeit| Null | A |
What I want to achieve is to combine the values together and end with a result like
|Application No | Status | Amount | Type |
==========================================
|90909090 | Forfeit| 3,000 | A |
I am new to SQL Query and have no idea how to do this
Thanks in advance

No need to join, use max() aggregate function and group by:
select applicationno, max(status), max(amount), max(type)
from yourtable
group by applicationno
However, if you have several non-null values for an application number in a field, then you may have to define a more granular rule than a simple aggregation via max.

Related

Is there a way in SQL to create a new column that looks at the values in a column that shares multiple rows to determine the value in the new column?

My data looks similar to what I've attached.
I'm wanting to create a new column that looks at the appt# and any row associated with that appt to see if that appt had the procedure D0330 and marks it yes or no.
So for example B Bradley's appt 8210 did include the procedure D0330. So the new column would be marked yes for both lines 1 & 2 despite line 2 not having that specific procedure in it's row.
What would be the best way to go about doing this?
Data
You can't define a column of a table that auto-generates a value based on multiple rows, or a subquery, or anything like that. Generated columns can only be based on simple functions that reference columns within the same row.
But you can reference a window of rows in a query, and produce a column of that query result, even though the column is not persisted in the table.
SELECT *, MAX(CASE `procedure` WHEN 'D0330' THEN 'Yes' ELSE 'No' END)
OVER (PARTITION BY employee) AS `newcolumn`
FROM mytable;
+------+-----------+-----------+------+-----------+
| line | employee | procedure | apt | newcolumn |
+------+-----------+-----------+------+-----------+
| 1 | B Bradley | D0330 | 8210 | Yes |
| 2 | B Bradley | D1226 | 8210 | Yes |
| 3 | C Connor | D1457 | 1130 | No |
| 4 | D David | D0330 | 543 | Yes |
+------+-----------+-----------+------+-----------+
Window functions require MySQL 8.0.

Why is Last selecting First in MS Access?

I have the follow SQL:
SELECT tbl_G_stats_atp.PK_G, tbl_G_stats_atp.InjuryCnt
FROM tbl_G_stats_atp
WHERE (((tbl_G_stats_atp.ID_A)=89) AND ((tbl_G_stats_atp.DATE_S)<37500))
GROUP BY tbl_G_stats_atp.PK_G, tbl_G_stats_atp.InjuryCnt;
It produces this result:
+---------+-----------+
| PK_G | InjuryCnt |
+---------+-----------+
| 1203857 | 0 |
| 1203881 | 0 |
| 1203890 | 0 |
| 1203913 | 0 |
| 1203916 | 0 |
| 1203989 | 0 |
| 1204001 | 0 |
| 1204102 | 0 |
| 1204172 | 0 |
+---------+-----------+
I want to select the last record so have used this SQL:
SELECT Last(tbl_G_stats_atp.PK_G) AS LastOfPK_G, tbl_G_stats_atp.InjuryCnt
FROM tbl_G_stats_atp
WHERE (((tbl_G_stats_atp.ID_A)=89) AND ((tbl_G_stats_atp.DATE_S)<37500))
GROUP BY tbl_G_stats_atp.InjuryCnt
ORDER BY Last(tbl_G_stats_atp.PK_G);
However it returns the first record (1203857).
I realise I can use this SQL as a replacement:
SELECT Max(tbl_G_stats_atp.PK_G) AS MaxOfPK_G, tbl_G_stats_atp.InjuryCnt
FROM tbl_G_stats_atp
WHERE (((tbl_G_stats_atp.ID_A)=89) AND ((tbl_G_stats_atp.DATE_S)<37500))
GROUP BY tbl_G_stats_atp.InjuryCnt;
However I'd like to understand why it's doing this. I may in future want to select the last record on a non-numeric field...
Have to be careful with using First or Last because records do not have intrinsic order. Even with an ORDER BY clause, results can be not as expected. I have avoided Last/First but just did a simple test and was able to return value from last record added to table - no WHERE, GROUP BY, or ORDER BY clauses included.
If you want to return all fields from that record, consider:
SELECT TOP 1 tbl_G_stats_atp.* FROM tbl_G_stats_atp WHERE ID_A=89 AND DATE_S<37500 ORDER BY PK_G DESC;
Even then, there must be a field of unique values that can be relied on to order records so desired record is brought to top. Usually an autonumber ID is positive and increasing (I've never seen otherwise) and should accomplish that. Or perhaps a date/time field will serve.

How do I use COALESCE and JOIN at the same time and including NULL values in MySQL?

I'm having trouble using COALESCE and JOIN at the same time. My plan is:
to match the venture column from my current table against the vid column from venture list table and return the corresponding venture name.
if the venture column on the current table is zero (0) or null, the other column next to it will be selected ("venture_other" column)
Although my query returns its proper values, it seems like NULL values are ignored in this case.
venture_list table:
-------------------
| vid | name |
-------------------
| 1 | Malaysia |
-------------------
| 2 | Singapore |
-------------------
request_forms:
---------------------------------------------
| fid | username | venture | venture_other |
---------------------------------------------
| 1 | jake.long | 2 | |
---------------------------------------------
| 2 | xander.f | 0 | Japan |
---------------------------------------------
Expected Result
---------------
| venturename |
---------------
| Singapore |
---------------
| Japan |
---------------
Actual Result
---------------
| venturename |
---------------
| Singapore |
---------------
Here's my query:
SELECT COALESCE(NULLIF(ventures.name, null), venture_other) AS venturename
FROM request_forms forms
JOIN venture_list ventures ON ventures.vid = forms.venture
I tried rearranging the column names, but didn't work.
The problem is that MySQL default behaviour on a JOIN is an INNER JOIN.
Obviously since there is no matching result for the second row in venture_list you only get 1 row back.
Try using LEFT JOIN THAT way the column ventures.name will result in NULL and thus venture_other will be used.
Your original use of NULLIF() here is peculiar. From the documentation:
Returns NULL if expr1 = expr2 is true, otherwise returns expr1.
So your statement said, "In the event that ventures.name is NULL then return NULL else return ventures.name". Which is superfluous since a NULL will already return a NULL because it's NULL.
Instead of the case, and properly using the NULLIF() you could have the NULLIF() return a NULL in the event that ventures.name is 0:
SELECT COALESCE(NULLIF(ventures.name, 0), venture_other) AS venturename
FROM request_forms forms
JOIN venture_list ventures ON ventures.vid = forms.venture
You were pretty close but need to change the nullif a bit:
select coalesce(nullif(ventures.name,0), venture_other) as venturename
from request_forms forms
join venture_list ventures
on ventures.vid = forms.venture;
Basically, you want to use nullif to null out ventures.name if it is 0..then the coalesce does the rest.

MySQL query with list of values

I have a table with over then 50kk rows.
trackpoint:
+----+------------+-------------------+
| id | created_at | tag |
+----+------------+-------------------+
| 1 | 1484407910 | visitorDevice643 |
| 2 | 1484407913 | visitorDevice643 |
| 3 | 1484407916 | visitorDevice643 |
| 4 | 1484393575 | anonymousDevice16 |
| 5 | 1484393578 | anonymousDevice16 |
+----+------------+-------------------+
where 'created_at' is a timestamp of row added.
and i have a list of timestamps, for example like this one:
timestamps = [1502744400, 1502830800, 1502917200]
I need to select all timestamp in every interval between i and i+1 of timestamp.
Using Django ORM it's look like:
step = 86400
for ts in timestamps[:-1]:
trackpoint_set.filter(created_at__gte=ts,created_at__lt=ts + step).values('tag').distinct().count()
Because of actually timestamps list is very very longer and table has many of rows, finally i getting 500 time-out
So, my question is, how to for it in ONE raw SQL query join rows and list of values, so it looks like [(1502744400, 650), (1502830800, 1550)...]
Where second first value is timestamp, and the second is count of unique tags in each interval.
First index created_at. Next build query like created_at in (timestamp, timestamp+1). For each timestamp, run the query one by one rather than all at once.

Display only one row for values that appear multiple times

I have multiple rows with the same name in this table, and I want to show only one of row of each. For example, with the following data:
| name | number |
+------+--------+
| exe | 1 |
| exe | 10 |
| exe | 2 |
| bat | 1 |
| exe | 3 |
| bat | 4 |
I would like to see the following results:
| name | number |
+------+--------+
| exe | 16 |
| bat | 5 |
How can I achieve this result?
Duplicate response: My question only have 1 table, the JOIN ..ON command creates confusion in understanding, i think this simple question can help many guys!
Try something like this:
SELECT t.`name`, SUM(t.`number`) AS `number`
FROM mytable t
GROUP BY t.`name`
ORDER BY `number` DESC
let the database return the result you want, rather than mucking with returning a bloatload of rows, and collapsing them on the client side. There's plenty of work for the client to do without doing what the database can do way more efficiently.
You can use an aggregation function for this:
SELECT name, SUM(number) AS total
FROM myTable
GROUP BY name;
Here is a reference on aggregate functions, and here is an SQL Fiddle example using your sample data.