How to SELECT DISTINCT one column and ORDER by another column? - php

I have a table like this
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
id | domain | domain_date | domain_status |
1 |abc_com | 2022-08-20 15:42:35 | 1 |
2 |def_com | 2022-08-20 15:44:31 | 1 |
3 |def_com | 2022-08-20 15:40:05 | 1 |
4 |abc_com | 2022-08-20 15:35:05 | 0 |
5 |ghi_com | 2022-08-20 15:25:05 | 1 |
6 |ghi_com | 2022-08-20 15:25:00 | 1 |
7 |abc_com | 2022-08-19 15:22:00 | 1 |
8 |ghi_com | 2022-08-20 15:25:05 | 1 |
9 |abc_com | 2022-08-20 15:21:00 | 1 |
10 |abc_com | 2022-08-19 15:21:20 | 1 |
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I want to get latest entries of five records from the table but I don't want duplicate domains.
I tried with SELECT DISTINCT, Distinct works fine if I select only domain it cuts the duplicates but if selects two columns
SELECT DISTINCT domain, domain_date FROM Domains
It still shows duplicates because the dates are different
What is the workaround for this?

if you group on max domain date, you will get a distinct list of domains with their max domain_date:
select
domain, max(domain_date) as MaxOfDomainDate
from table
group by domain
We can join the table on this result set if we want to get the status that goes with the domain record for that date:
select A.domain, A.domain_date, A.domain_status
from
table A
inner join
(
select
domain, max(domain_date) as MaxOfDomainDate
from table
group by domain
) B
on A.domain = B.domain
and A.domain_date = B.domain_date;
You should be able to add ordering and TOP or LIMIT to such a query pretty easily to get the "latest 5" and so on (I'll leave that as an exercise to the reader ;) )

I think that you may want domain_date values to be unique.
SELECT DISTINCT domain WHERE domain_date UNIQUE

Related

Finding inner join mysql with array [duplicate]

This question already has answers here:
How to join two tables using a comma-separated-list in the join field
(5 answers)
Closed 2 years ago.
I have two tables, First one is products where it has list of products with some specifications, in the other hand I have a table with clients and what type of product they want, they might want a product in any town of a list exactly as explained in the following tables,
Products Table like
| id | owner | userid | city | town | status | price |
| 1 | jon spee | 10 | 10 | 4 | 0 | 10500 |
| 2 | Hiss Roe | 10 | 7 | 9 | 0 | 20000 |
| 3 | John Smi | 10 | 10 | 12 | 0 | 10000 |
Clients Table like
| id | fullname | userid | city | towns | status | price |
| 1 | name 1 | 10 | 10 |4,8,6,2| 0 | 20000 |
| 2 | name 2 | 10 | 7 | 7,2,9 | 0 | 25000 |
| 3 | name 3 | 10 | 10 | 1 | 0 | 20000 |
MySQL Query :
SELECT *
FROM clients
INNER JOIN products
ON (
clients.userid = products.userid AND
clients.price >= products.price AND
clients.city = products.city AND
clients.status = products.status
I want it to check also in towns like for each town it executs this query (dynamically),
(products.town LIKE '%4%' OR products.town LIKE '%8%' OR products.town LIKE '%6%' OR products.town LIKE '%2%')
You could go with this query
SELECT *
FROM clients
INNER JOIN products
ON (
clients.userid = products.userid AND
clients.price >= products.price AND
clients.city = products.city AND
find_in_set(clients.town, products.town) AND
clients.status = products.status
you can also fetch it in php and create your statement based on the results fetched
Your primary effort should go into fixing your data model. Don't store multiple integer values in a string column. You should have a separate table to store the relation betwen clients and towns, which each tuple on a separate row.
That said: for your current design, you can join on find_in_set():
on
clients.userid = products.userid
and ...
and find_in_set(product.town, client.towns)

SQL query to return combined data of all rows that don't belong to current user

Imagine this is my table:
----------------------------------------------------
| id | user_id | amount_1 | amount_2 | amount_3 |
----------------------------------------------------
| 1 | 1 | 2 | 3 | 4 |
----------------------------------------------------
| 2 | 2 | 2 | 1 | 1 |
----------------------------------------------------
| 3 | 2 | 1 | 2 | 2 |
----------------------------------------------------
| 4 | 3 | 2 | 1 | 4 |
----------------------------------------------------
I need a query that gives me one result set for every entry that belongs to my current user, and then returns everything else as a single combined row with the amounts summed.
So in this case if I am user 1, I should get the following rows back:
---------------------------------------
| id | amount_1 | amount_2 | amount_3 |
---------------------------------------
| 1 | 2 | 3 | 4 | my own amounts
---------------------------------------
| 2 | 5 | 4 | 7 | everyone else's amounts
---------------------------------------
Any tips?
I've considered it might be a better idea to just filter the data in the code (php). Please help i'm starting to hate myself
You could use a UNION in sql
select 1 id, amount_1, amount_2, amount_3
from my_table
where user_id = 1
union
select 2 , sum(amount_1) , sum(amount_2), sum(amount_3 )
from my_table
where user_id <> 1
You can do with one query using union:
SELECT user_id, amount_1, amount_2, amount_3
FROM table
WHERE user_id = YOUR_USER_ID
UNION
SELECT -1, SUM(amount_1) AS amount_1, SUM(amount_2) AS amount_2, SUM(amount_3) AS amount_3
FROM table
WHERE user_id != YOUR_USER_ID
You can use aggregation in one fell swoop:
select (case when user_id = 1 then id end) as my_user_or_not,
sum(amount_1), sum(amount_2), sum(amount_3)
from t
group by my_user_or_not;
The null values in the first column indicate another user. You have labelled the column id, which is a bit problematic if you were -- for instance -- to choose user_id = 2 in your example. NULL seems safer for this purpose.

MySQL Select to create a rank based on number of entries from a table...how to do it?

What I Have:
Table 1 : USERS (autoID, name, etc)
Table 2 : TROPHIES (autoID, name, etc)
Table 3 : VIEWS (userID, timestamp, etc)
Table 4 : CANDIDATES (userID, trophyID, etc)
What I Know:
USERS.autoID & TROPHIES.autoID
How I Do It:
I have this TROPHIES table where I store different categories users can be nomitated to.
Each User can be nominated for 1,2 or more trophies from TROPHIES table.
In the VIEWS table I store each view of the profiles for each individual user with USERS.autoID, timestamp and other data.
In the CANDIDATES table I store the TROPHIES.autoID and USERS.autoID - this way I know which User is nominated for which Trophy.
What I Need to Know
Knowing USERS.autoID & TROPHIES.autoID I want to make a TOP based on the number of entries in the last 3 days for example in VIEWS table of all USERS that are listed in CANDIDATES table for that specific trophy and find out the POSITION on that top of a specific user.
So let's say the user with the autoID 1 is nominated to the TROPHY with the autoID 10 and has 100 entries in the VIEWS table on the last 3 days but there are other 3 users nominated to the TROPHY with the autoID 10 who have more than 100 entries in the last 3 days so...I need a select that would return the number 4.
My Questions:
Can I do that with 1 single SELECT query? If yes...how? If no...how could I make this query to spend as little resources as possible.
Thanks!
[EDIT]
Here is some data
TABLE 1 - USERS
+--------+-------+
| autoID | name |
+--------+-------+
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
+--------+-------+
TABLE 2 - TROPHIES
+--------+------------+
| autoID | name |
+--------+------------+
| 1 | Baseball |
| 2 | Basketball |
| 3 | Boxing |
+--------+------------+
TABLE 3 - VIEWS
+--------+--------+------------+
| autoID | userID | timestamp |
+--------+--------+------------+
| 1 | 2 | 1551632970 |
| 2 | 2 | 1551632971 |
| 3 | 3 | 1551632972 |
| 4 | 1 | 1551632973 |
| 5 | 2 | 1551632974 |
| 6 | 1 | 1551632975 |
| 7 | 3 | 1551632976 |
| 8 | 1 | 1551632977 |
| 9 | 2 | 1551632978 |
| 10 | 3 | 1551632979 |
| 11 | 3 | 1551632980 |
| 12 | 3 | 1551632981 |
+--------+--------+------------+
TABLE 4 - CANDIDATES
+--------+--------+----------+
| autoID | userID | trophyID |
+--------+--------+----------+
| 1 | 2 | 1 |
| 2 | 3 | 3 |
| 3 | 1 | 2 |
| 4 | 1 | 1 |
+--------+--------+----------+
In the end I want to be able to know on which position a User is for a specific trophy based on the entries from the VIEWS table.
Let's say I want to check the position of the USER with the autoID = 1 for Baseball (trophy which has autoID = 1) after timestamp 1551632972.
So...First we have to see which users are listed in this trophy so we can ignore the entries from the table VIEWS for the other users. Trophy with the autoID 1 (Baseball) has only two users listed - user1 and user2.
Now I want to see how many entries both have so I can be able to find out which is the position of the user1 on this top.
So if we select and count all the entries from the table VIEWS for user1 where timestamp is equal or bigger than 1551632972 we will get number 3 and if we do the same thing for the user2 we will get 2 and since 3 is bigger than 2, user1 will be on 1st place and user2 will be on the 2nd place.
I am searching for a way to get the place in the TOP for a specific user inside a specific sport using a single MySQL query (if possible) or finding the best solution to do so...
I found the solution...I will just leave it here in case someone else will need it.
SELECT
U.autoId,
U.name,
U1.position
FROM USERS U
JOIN (SELECT
#rownum := #rownum + 1 AS position,
U.autoId,
U.name,
COUNT(V.autoID) as "Nr"
FROM USERS U
JOIN VIEWS V ON V.userID= U.autoID
JOIN CANDIDATESC ON C.userID= U.autoID
JOIN (SELECT #rownum := 0) R
WHERE C.trophyID= 'id_of_trophy_wanted' GROUP BY U.autoID ORDER BY Nr DESC) as U1 ON U1.autoID =
U.autoID
WHERE U.autoID = 'id_of_user_wanted'
Thanks to the ones who tried to help!

How to select rows from MySQL table with max values

I have a table with multiple rows for each customer and and a visit_date. The visit date can be null as well.
My tables are as below:
customers:
id | name | email
1 | John Doe1 | a.b#gmail.com
2 | John Doe2 | b.c#gmail.com
3 | John Doe3 | x.y#gmail.com
store_customers
id | customer_id | store_id | email_optedin | visit_date
1 | 1 | 1 | 1 | 2015-11-30
2 | 1 | 2 | 1 | 2016-05-08
3 | 1 | 3 | 1 | null
4 | 2 | 1 | 1 | 2015-04-30
5 | 2 | 2 | 1 | 2015-08-40
6 | 2 | 3 | 1 | 2015-12-12
7 | 3 | 1 | 1 | null
8 | 3 | 2 | 1 | null
9 | 3 | 3 | 1 | null
I am trying to retrieve customers who either have not had a visit to the any of the three stores or have not visited since a specified date (e.g. 2016-04-15).
I am expecting customers 2 and 3 but not 1.
I tried this query:
select distinct * from customers
inner join store_customers on store_customers.customer_id = customers.id
where customers.email != '' and
store_customer.store_id in (1,2,3) and customers.emailStatus not in ('Unverified','Bounced','Spammed')
and
(
store_customer.email_optedin = 1
and max(store_customers.visit_date) <= '2016-04-15'
or account_customer.visit_date is null
);
This does not work. I somehow need to, for the set of store ids), I need to select customers who have either not had any visit (all nulls for visit date for the specified stores) or the if one or more visit dates are available then compare the max date to the specified date.
I found similar questions but none of the answers has worked for me, mainly because of the requirement of selecting either those customers who have no visit or if they do atleast one, then to compare the latest visit date from the set of stores in the joined table.
I am trying to do this all in one query but if that is not possible then I can break it up as well. I also do not want to change the order of joins because there are many other things added on to this query and changing the order of joins may become a problem.
I really appreciate any help that can be provided.
Regards,
Waqar
Try this query
SELECT
customers.id,
customers.name,
MAX(store_customers.visit_date)
FROM
customers LEFT JOIN store_customers on customers.id = store_customers.customer_id
GROUP BY customers.id,customers.name
HAVING MAX(store_customers.visit_date) < '2016-04-15' OR MAX(store_customers.visit_date) IS NULL

mysql group by select with conditional value

In my messages table I have following rows for example,
|----|---------|--------------|------|
| id | user_id | message |status|
|====|=========|==============|======|
| 1 | 2 | msgs 11 | r |
|----|---------|--------------|------|
| 2 | 3 | msgs 12 | r |
|----|---------|--------------|------|
| 3 | 2 | msgs 13 | r |
|----|---------|--------------|------|
| 4 | 3 | msgs 14 | u |
|----|---------|--------------|------|
Now, I need to know two things for each user_id
Whether it has any status u or not.
How many messages are there
For example, a query like below
select user_id, status, count(*) as totalMsg from messages group by user_id
Would brought me following rows
| user_id | status| totalMsg |
|=========|=======|==========|
| 2 | r | 2 |
|---------|-------|----------|
| 3 | r | 2 |
^
|------> I need this value to be 'u' because user 3 has a message u
My current query doesnt really gurantee that it will look for a u in the status column.
Is that possible to do? If so how?
MAX() will work on this since r is the least value based on the lexicographical order.
SELECT user_ID,
MAX(status) status,
COUNT(*) totalMsg
FROM messages
GROUP BY user_ID

Categories