I have two tables one that contains a huge list of items and another that trading for those items.
Here are examples tables:
The main table
| ID | TITLE | STATUS | TRADE |
-------------------------------
| 1 | test1 | 1 | 1 |
| 2 | test2 | 1 | 1 |
| 3 | test3 | 1 | 0 |
| 4 | test4 | 0 | 1 |
The trade table
| ID | TRADER | ITEM | URL |
------------------------------------------------------
| 1 | 2 | 1 | HTTP://www.test.com/itemOne |
| 2 | 5 | 3 | HTTP://www.test.com/itemThree |
| 3 | 5 | 4 | HTTP://www.test.com/itemFour |
Say I want to have a list of all the items that are not being traded by trader 5 and have a status of 1. So when trader 5 comes to the site they will be able to select the remaining items to trade.
Here is what I have tried:
$sql = "SELECT m.id, m.title
FROM main AS m, trade AS t
WHERE m.trade >= 1 && m.status = 1 &&
t.trader <>". mysql_real_escape_string($traderID);
This code just doesn't work. Any ideas on this?
It is not clear to me what column in Trades is an FK to Main. Below, I have assumed it is the Item column:
select m.id, m.title
from Main m
where not exists (
select *
from trade
where m.id = item
and trader = 5
)
and m.status = 1
Try this:
SELECT id, title FROM main
WHERE status = 1 AND id NOT IN
(SELECT item FROM trade WHERE trader = 5);
This will grab a list of every title in main with a status of 1, but limit the items based on a subquery which gets a list of ids already traded by trader 5 (i.e. items "not in" the list of items returned as having been traded by trader 5).
I'll leave it to you to update the query to be parameterized as needed.
Note that I'm assuming that item in trade is a foreign key to the id field in main, since you didn't specify it.
Related
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)
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!
Products :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 2 | A | Dell | 0 |
--------------------------------------------
| 3 | B | Dell | 1 |
--------------------------------------------
| 4 | B | Dell | 1 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
| 6 | C | Dell | 1 |
--------------------------------------------
Hi everyone, i have a table (products) stored in MySql with many records, for now i'm using this query SELECT * FROM products WHERE sold = 0, in results i get :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 2 | A | Dell | 0 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
i want to get only one record from each group, so the results will be like :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
You could easily do this by using a distinct clause and removing the id column. If you want to keep the id column you need to specify how one would chose which id to keep.
select distinct
`group`
, name
, sold
from
products
where
sold = 0;
To keep the row with the smallest id (as your example shows) something along the lines of the example below would work.
select
id
, `group`
, name
, sold
from
products
where
sold = 0
and id = (
select
min(p.id)
from
products p
where
p.`group` = products.`group`
and p.sold = 0
);
First, change your field named Group to something like Group_Name. GROUP is a reserved keyword, and if it is not causing you problems now it probably will later.
Second, you should ask yourself what you are really after. The following query should generate your desired result. It adds an additional condition where the IDs that are returned are the lowest numbered ID in each group.
SELECT * FROM products
WHERE sold = 0
AND ID IN (SELECT MIN(ID) FROM products WHERE sold = 0 GROUP BY Group_Name)
Why do you want that, though? That is not a normal desired end state. You should ask yourself why you care about the ID. It looks like your goal is to figure out which products have not sold anything. In that case, I would recommend this instead:
SELECT DISTINCT Group_Name, Name
FROM products
WHERE sold = 0
ORDER BY Group_Name, Name
I found the solution by using the statement GROUP BY,
SELECT * FROM products WHERE sold = 0 GROUP BY group
in the results now, i get only one record for each group and the minimal id without adding any other statement, and in my real table i am using product_group instead of group because it's a reserved word.
Try this:
SELECT `ID`, `Group`, `Name`, `Sold` FROM products WHERE sold = 0 GROUP BY `Group`;
I have the following problem: I have a table import_data
The table is enriched something like this
| id | profile_id | sku | vendor | price | importRun |
| 1 | 39 | 123 | myVen | 2.0 | 1 |
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
What I need to get is an output of all elements, but only once. Every sku must be unique. To make it even worse, I need the newest data, if they are redundant.
My output should be like this:
| id | profile_id | sku | vendor | price | importRun |
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
Short Summary about the structure:
ID = PK
sku = a unique identifier for an article
importRun = Needed for comparision.
So, to explain it: I have an import-script, which reads a given CSV-file and imports all articles listed in it. I get this CSV-file in a regular period (once a week). I need to collect all data and save it, to create a price-evolution later on.
After every Import, I increment the number of importRun, so that no information is lost (remember, I can't use REPLACE INTO or INSERT IGNORE.
Now, when I export it, I need the newest Data, if a SKU occures multiple times. In this case, the SKU 123 is inserted 2 times on 2 different runs. That means, since my newest Run had the number 2, I need this tupel (and ignore the first one).
When I work with DISINCT, it would still output the same table, since they aren't distinct at all, because importRun differs.
I should be able to use GROUP BY, but I couldn't figure out which value will be taken, the first- or the last one? (importRun 1 or 2)
Update 1
Followed by the idea of #mitkosoft, I tried the following:
SELECT DISTINCT t1.*
FROM import_data t1
INNER JOIN import_profiles imp on t1.profile_id = imp.id
INNER JOIN (
SELECT DISTINCT sku, MAX(importRun) AS importRun
FROM import_data
GROUP BY sku ) t2
ON t1.sku = t2.sku
WHERE imp.creditornr = 73329
AND t1.vendor = 'rackmountit'
AND t1.importRun = t2.importRun
** Update 2 **
I added the complete Structures for all tables, which are relevant.
Import-Data:
|
Import-Profiles
But i still get duplicates :/
All you need to do is to determine MAX(importRun) for each sku:
SELECT
t1.*
FROM
import_data t1
INNER JOIN (
SELECT sku, MAX(importRun) AS importRun FROM import_data GROUP BY sku
) t2
ON t1.sku = t2.sku
AND t1.importRun = t2.importRun
Output is:
+----+------------+-----+--------+-------+-----------+
| id | profile_id | sku | vendor | price | importRun |
+----+------------+-----+--------+-------+-----------+
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
+----+------------+-----+--------+-------+-----------+
2 rows in set
Perhaps you could join on the same table where sku = sku
I have two tables that have these columns (I'm only showing revelant ones) :
tasks table
+----+------+
| id | todo |
+----+------+
| 1 | 0 |
| 2 | 1 |
| 3 | 1 |
| 4 | 0 |
| 5 | 1 |
+----+------+
entries table
+----+---------+---------+------+
| id | task_id | user_id | done |
+----+---------+---------+------+
| 1 | 3 | 1 | 1 |
| 2 | 5 | 2 | 1 |
| 3 | 5 | 1 | 1 |
| 4 | 2 | 1 | 0 |
+----+---------+---------+------+
I query these tables and only keep tasks where todo = 1, So I already have the data in a PHP object.
I then have two lists that the user can view : tasks that are to do, and archived (done), and tasks that are to do. I can generate the first list just fine, I'm looping through each task and entries if they have a matching task_id where user_id == $loggeduser && done == 1, and unsetting the index of those that don't match. However, I cannot find a logic to do this with my archive list, as I don't have entries to match. How do I loop my tasks and only keep those that are done, for the user? In this case, for the archive list for user 1, I'm excepting to only keep task id 3 and 5, and for user 2, only keep task id 2.
Thanks.
You can do all this using plain SQL (I suppose you're using some relational database).
This query gives you all the tasks "todo & done". To get the tasks "todo & not done", just change the "e.done = 1" to "e.done = 0". I'm sure you get the idea.
SELECT * FROM tasks t
INNER JOIN entries e ON t.id = e.task_id
AND e.user_id = [logged_user_id]
AND e.done = 1
WHERE
t.todo = 0