sql conditional when users id does not show up in another table - mysql

I have two tables, both contains a created_at column.
users: id, first_name, last_name, created_at
entries: id, user_id, created_at
Below is the query that returns all entries and the users, but I need to add a conditional to display the appropriate created_at date
select users.id, first_name, last_name, entries.created_at
from users left join sweepstakes_entries on users.id = entries.user_id;
I imported a csv of mail-in entries into the users table and I need to write a sql statement that returns all entries with the user that entered them, as well as the mail entries I entered into the users table.
I used a left join to return the users that were imported from the csv file, since they don't have any entries in the entries table, but I still need to return them in the sql results.
With that said, I need to display the created_at date for when the entry was created from the entries table (entries.created_at), but I need to do a conditional on the created_at so when it pulls in the users (users who were imported from the mail-in csv) it will not have a created_at date from the entries table to tie it to, so I need to do a conditional that instead of using entries.created_at, I use users.created_at.
In theory:
if(this record's users.id does not show up in the entries table)
use users.created_at as created_at
else
use entries.created_at as created_at

You have multiple options:
Use COALESCE - Returns first non null value from a list. SELECT COALESCE(Col1, Col2, Col3)
Use CASE WHEN, THEN to check if Col1 is null or = "0000-00-00" return Col2 or vice versa

By the sounds of it you could simply use COALESCE
select users.id,
first_name,
last_name,
COALESCE(entries.created_at, users.created_at) AS created_at
from users
left join sweepstakes_entries on users.id = entries.user_id;
You could also use the less portable IFNULL:
IFNULL(entries.created_at, users.created_at) AS created_at

Related

SQL: Window function after Join

I have two tables: Subscriptions and Items:
Subscriptions (sub_id PK, user_id, value)
Downloads (download_id PK, user_id, category_id)
My goal is to get a result table of form (user_id, sum_subscription_value, num_download_categories). In other words: each row is unique to a user_id, in which the total value of subscriptions that user has purchased is given alongside the number of categories the user has downloaded things from.
I've attempted by solving using the following code, but the categories aren't being counted correctly. I think the issue might be the join, as the value rows are being repeated, but I'm not sure how to exactly circumvent the issue. Any help is appreciated
SELECT
DISTINCT subscriptions.user_id,
SUM(value) OVER (PARTITION by subscriptions.user_id, category_id) AS user_purchases,
COUNT(category_id) OVER (PARTITION by subscriptions.user_id) AS user_downloads
FROM subscriptions
LEFT JOIN downloads on subscriptions.user_id = downloads.user_id;
My goal is to get a result table of form (user_id, sum_subscription_value, num_download_categories).
One method is to aggregate before joining. But in this case, I suppose that a user could be missing from either table. And aggregating before would require full join to avoid losing data.
Instead, you can use union all and group by:
select user_id,
sum(value) as subscription_value,
count(distinct category_id) as num_categories
from ((select user_id, value, null as category_id
from subscriptions
) union all
(select user_id, NULL as value, category_id
from downloads
)
) sd
group by user_id;

sql Summarising table columns by e-mail

I have a table (SQL) where customers can have different statuses. Each status is noted with a date in a separate column.
Currently, however, the customer record is not enriched with the new status including the time stamp. As soon as a customer receives a new status, it is entered in the table.
Now I would like to merge these different timestamps of the individual customers into one row in a sql query and export it as a csv.
The email address serves as the identifier here.
How can I write the sql query so that I have the statuses of the customer abc#gmx.net in one row?
I look forward to your feedback.
One way to do it is to join your table multiple times. here is an example fiddle
http://sqlfiddle.com/#!9/ca5f74/3
select t.email,t1.date1,t2.date2
from t
inner join t as t1 on t.email = t1.email and t1.date1 is not null
inner join t as t2 on t.email = t2.email and t2.date2 is not null
group by t.email,t1.date1,t2.date2
email date1 date2
a 1/1/2011 2/2/2022
You can use aggregation:
select email, max(col1), max(col2)
from t
group by email;

Convert Postgres query with distinct on to MySQL query

I have a table users:
Where id is a primary key.
I want to select all columns, but all usernames should be unique. I don't care which ids will be in an expected result, but anyway I need them. For that I use the following query in Posgres 10:
select distinct on (username) * from users;
That gives me the result I want:
How can I achieve the same, but using MySQL query?
Your query doesn't make sense in Postgres because it lacks an order by. For this query:
select distinct on (username) u.*
from users u
order by username, id desc;
You can write this as:
select u.*
from users u
where u.id = (select max(u2.id) from users u2 where u2.username = u.username);
Assuming id is unique, this will return one row per username.
I believe this is the conversion of that
SELECT id, username FROM users group by id
You can find more info on this link:Converting SELECT DISTINCT ON queries from Postgresql to MySQL
Extra Note: You can use this http://www.sqlfiddle.com/#!9/0bd1a2/1 to test your SQL which maybe helpful for you in converting Postgres to SQL

Query to find users with one row in table

I have a table "users" which has multiple columns in which column "status" has multiple values like 1,0,3,2,4. There is column "user_id" which doesn't contain unique values since, this is foreign key of another table called "user_master".
so here in "users" table we have multiple values of the one user.
So, Here is my actual query is that i would like to write a sql query to find users has only one entry in table "users" with particular status value.
For e.g. I would like to fetch all such users with status=2 and their entry in table is not more than 1. Like if user has multiple entries with status 2,1,4 in table which should not be return in query.
It should yield those users which has only one entry in table and which is of status = 2
That must be what you use:
Select count(u.user_id) AS cnt, u.*
from user u
where u.status = 2
group by u.user_id, u.status
having cnt = 1;
WITH tmp AS(
SELECT Stud_Id,COUNT(*) AS 'Count' FROM Student_tbl GROUP BY Stud_Id
)
SELECT * FROM tmp WHERE Count = 1 AND Status = 2
You have to add field in GROUP BY Clause whichever you want to use in SELECT clause.
I have researched it and found answer for it.
And query goes like this.
select count(id) as cnt,
user_id,status from users
group by user_id
having cnt < 2 and status=2
First it will group the things having count less than 2 and then which will check for status.

MySQL get most recent entries from a big table

I have a table with more than 50k entries and a few users:
transactions Table:
ID
USER
VALUE
TIMESTAMP
users Table:
USER
TYPE
REGION
I would like to get the most recent transactions for each user. So far I am using the following GROUP BY statement, but it is slow (takes 5-10sec approx):
select ID , max(TIMESTAMP) as TIMESTAMP from transactions group by USER;
Is there a faster statement to retrieve the most recent entries?
First of all as per my understanding ID columns should keep unique values in transaction table so group by should be on USER field as per your requirement.
Further you can try below query. I am not sure but you can compare its time with your query and use accordingly.
SELECT
USER , TIMESTAMP
FROM
(SELECT USER,TIMESTAMP FROM transactions ORDER BY ID DESC) a
GROUP BY USER;
Assuming there will be an index on USER column as this is common between both tables.
Try this,
select u.*,tr.* from users as u
outer apply
(
select top 1 * from transactions as t
where t.USER= u.USER
order by t.ID desc
)as tr