I have set up a php page so there are multiple options for data input that gets put into multiple temporary tables, each one separated with querying the database based on 1 condition given in the data input. So if the input is age > 10 and shoesize > 6 and height > 60, there will be three temporary tables table0, table1, and table2 where table0 is only data age > 10 and table1 is only data shoesize > 6 and table 2 is only data height > 60.
I am wondering how to intersect these so I will only get the results that have all requirements met with age > 10 and shoesize > 6 and height > 60. My attempt using the "WHERE EXISTS" clause is below but it doesn't work.
SELECT *
FROM table0 t0
WHERE EXISTS
(SELECT *
FROM table1 t1
WHERE EXISTS
(SELECT *
FROM table2 t2
WHERE t0.age = t1.age = t2.age
AND t0.shoesize = t1.shoesize = t2.shoesize
AND t0.height = t1.height = t2.height));
Note that queries like this without relying on a table's primary key become cumbersome, so I'd recommend you add a primary key.
That said, the query you need is quite close to what you had already attempted:
SELECT *
FROM table0 t0
WHERE EXISTS (
SELECT 1
FROM table1 t1
WHERE t1.age = t0.age AND t1.gender = t0.gender
AND t1.shoesize = t0.shoesize AND t1.weight = t0.weight
AND t1.height = t0.height AND t1.eyes = t0.eyes) AND
EXISTS (
SELECT 1
FROM table2 t2
WHERE t2.age = t0.age AND t2.gender = t0.gender
AND t2.shoesize = t0.shoesize AND t2.weight = t0.weight
AND t2.height = t0.height AND t2.eyes = t0.eyes)
Note: The query above will work only if none of the values is NULL.
Related
I have a MySQL query as below; I would like to select the top record for each range of 600 records in a table with 1.8M records. So far I have to loop 3,000 times to accomplish this which is not an efficient solution.
Database Schema;
Table: bet_perm_13predict
id bet_id perm_id avg_odd avg_odd2 avg_odd3
1 23 1 43.29 28.82 28.82
2 23 2 42.86 28.59 28.59
3 23 3 43.13 28.73 28.73
Table: bet_permute_13games
perm_id perm_code
1 0000000000000
2 0000000000001
3 0000000000002
4 0000000000010
Sample MySQL Query in PHP
$totRange = 0; //Used as starting point in rang
$range = 600; //Used as range
$stop = 0;//Used as endPoint of range
while($totRange < 1800000){
$stop = $totRange+$range;
$sql = "SELECT (tb1.avg_odd2 + tb1.avg_odd3) AS totAvg_odd ,
tb1.perm_id , tb1.avg_odd, tb1.avg_odd2, tb1.avg_odd3, tb2.perm_code
FROM bet_perm_13predict tb1
INNER JOIN bet_permute_13games tb2 ON tb2.perm_id = tb1.perm_id
WHERE tb1.bet_id = '$bet_id' && tb1.perm_id
BETWEEN $startRange AND $stop ORDER BY totAvg_odd ASC LIMIT 1"
$q1 = $this->db->query($sql);
$totRange = $stop;
}
In other words I want to select a sample of the data that will represent the entire table with the sample not being random but predefined using the top record in range of 600. So far I have no idea how to proceed. There is no clear online material on this subject.
You can use integer division to create groups.
DEMO
SELECT ID, ID DIV 600 as grp
FROM Table1
Then find the max value on each group. Some options here
Get records with max value for each group of grouped SQL results
For those who might encounter the same issue, this is how I solved it. I used #Juan Carlos suggestion and added a way to pick top record of group using Subquery.
SELECT * FROM
(SELECT * , perm_id DIV $limit as grp , (avg_odd2 + avg_odd3) AS totAvg_odd
FROM bet_perm_13predict WHERE bet_id = '$bet_id' ORDER BY grp ASC ) tb1
INNER JOIN bet_permute_13games tb2 ON tb2.perm_id = tb1.perm_id
INNER JOIN bet_entry tb3 ON tb3.bet_id = tb1.bet_id
WHERE tb1.avg_odd2 < (SELECT AVG(avg_odd2) FROM bet_perm_13predict WHERE bet_id = '$bet_id' )
&& tb1.avg_odd3 < (SELECT AVG(avg_odd3) FROM bet_perm_13predict WHERE bet_id = '$bet_id' )
GROUP BY grp ORDER BY totAvg_odd ASC
LIMIT 100
I have the PHP code:
$query = mysqli_query($mysqli, "SELECT * FROM `table_1`");
$result = mysqli_num_rows($query);
$queryTwo = mysqli_query($mysqli, "SELECT * FROM `table_2`");
$resultTwo = mysqli_num_rows($queryTwo);
$number = $result + $resultTwo;
return $number;
The point is that sometimes, the $number variable is returning NULL,
when it should not supposed to do that.
I have always rows in those 2 tables, and the returned result should not be NULL, ever.
Is this a correct approach to sum the number of rows from 2 tables? I don`t understand why sometimes I get NULL instead of a number.
Well, I would suggest you to do it like
select ( select count(*) from Table1 ) + ( select count(*) from Table2 )
as total_rows
executing this query and getting the value of total_rows will return you true result
Or you can create a stored procedure to do the same thing. as explained below
CREATE PROCEDURE sp_Test
AS
-- Create two integer values
DECLARE #tableOneCount int, #tableTwoCount int
-- Get the number of rows from the first table
SELECT #tableOneCount = (SELECT COUNT(*) FROM Table1
WHERE WhereClause)
SELECT #tableTwoCount = (SELECT COUNT(*) FROM Table2
WHERE WhereClause)
-- Return the sum of the two table sizes
SELECT TotalCount = #tableOneCount + #tableTwoCount
Why don't you go with only one query like this:
you will have the result directly in one step and it will avoid contacting the DB twice to fetch intermediate result and it will also simplify your program!
SELECT
(select count(*) from table_1)
+
(select count(*) from table_2)
I have 2 tables.
Table A: trades: which contains the columns: tradeID, tradeName, tradeShow, and tradeGuy.
Table B: offers: which contains the columns: tradeID, offerName, offerGuy.
I'm trying to select all columns from table A (trades) WHERE the value of "tradeShow" = 'Yes', And the value of "tradeGuy" != the user's Username. That much is easy, but I also don't want to select any records which have an offer created by the user. In other words, in table B (offers), offerGuy != Username WHERE trade ID from Table B = tradeID from Table A.
But, how do I merge these 2 conditions? I've tried this:
$sql = "SELECT *
FROM trades t1
JOIN offers t2
ON (t1.tradeID = t2.tradeID)
WHERE t1.tradeShow='Yes' AND t1.tradeGuy!='$username' AND t2.offeringGuy!='$username'";
But the problem with that is it only selects the records from trades which have an offer, because of the forth line: ON (t1.tradeID = t2.tradeID), as in it only selects trades which have a record in (offers) that mentions their tradeID.
I've also tried an awkward attempt to link the 2 tables with a meaningless link by adding a "linker" column to each table with the default value of "XXX", and did this:
$sql = "SELECT *
FROM trades t1
JOIN offers t2
ON (t1.linkerA = t2.linkerB)
WHERE t1.tradeShow='Yes' AND t1.tradeGuy!='$username' AND (t2.offeringGuy!='$username' WHERE t1.tradeID=t2.tradeID)";
But the problem with that is using 2 Where clauses...
So, how do I merge the 2 conditions?
What you're looking for is called an OUTER JOIN (in this case a LEFT OUTER JOIN) which will give you null results for missing matches, something like;
SELECT *
FROM trades t1
LEFT OUTER JOIN offers t2
ON t1.tradeID = t2.tradeID AND t2.offeringGuy = '$username'
WHERE t1.tradeShow='Yes' AND t1.tradeGuy!='$username' AND t2.offeringGuy IS NULL
We add a condition to the LEFT JOIN that we're only interested in matches against t2.offeringGuy = '$username', which will return NULL values in t2's fields if there is no match.
Then we just check that t2.offeringGuy IS NULL to find the non matches.
I would do this with not exists rather than an explicit join:
SELECT *
FROM trades t
WHERE t.tradeShow = 'Yes' AND t.tradeGuy <> '$username' and
not exists (select 1
from offers o
where t.tradeID = o.tradeID and o.tradeGuy = '$username'
);
I have a mysql table which looks something like this:
id_one id_two
1 2
2 1
3 2
2 3
4 5
5 4
I want to delete rows with two duplicate values inrespective of which columns they are in so the example would look like this:
id_one id_two
1 2
3 2
5 4
There are over 12 million rows in total. Any ideas on how I should do this?
Php or mysql query would be preferred.
DELETE a
FROM table1 a
LEFT JOIN
(
select id_one, id_two
from Table1
GROUP BY least(id_one, id_two), greatest(id_one, id_two)
) b ON a.id_one = b.id_one AND a.id_two = b.id_two
WHERE b.id_two IS NULL
SQLFiddle Demo
I would advise a 2-step approach:
Make id_one always the smaller value, i.e., if id_one is larger than id_two then swap their values - consider something like this (taken from here):
UPDATE tablename
SET id_one = (#temp:=id_one), id_one = id_two, id_two = #temp
WHERE id_one > id_two
Remove the duplicates as described here:
DELETE tablename FROM tablename INNER JOIN
(SELECT min(primary_key) AS min_id, id_one, id_two FROM tablename
GROUP BY id_one, id_two
HAVING count(1) > 1) AS d
ON (d.id_one = tablename.id_one
AND d.id_two = tablename.id_two
AND d.min_id <> tablename.primary_key)
(I assume that you will have a primary key on a table that holds 12 million entries.)
Not tested, so please backup your data!
DELETE FROM ztable zt
WHERE zt.id_one > zt.id_two
AND EXISTS (
SELECT *
FROM ztable tx
WHERE tx.id_one = zt.id_two
AND tx.id_two = zt.id_one
)
;
won't work in mysql, because in mysql you cannot reference the table being updated or deleted.
Since you want to make a backup copy anyway, you could use that instead in the EXISTS subquery:
CREATE table safetable AS (SELECT * from ztable);
DELETE FROM ztable zt
WHERE zt.id_one > zt.id_two
AND EXISTS (
SELECT *
FROM safetable tx
WHERE tx.id_one = zt.id_two
AND tx.id_two = zt.id_one
);
I have 2 tables in database: table_1 and table_2.
table_1 contains 3 column namely a_id, a_zone, a_address
table_2 contains 4 column namely p_id, not_use, p_zone, p_address
The row numbers are not same in the 2 tables. I need to compare the "DATA SET" of the (a_zone, a_address) from table_1 with (p_zone, p_address) from table_2.
Let me give you an example:
Table1 contains:
a_zone a_address
=================
1 8
2 9
3 6
4 9
5 2
Table2 contains:
p_zone p_address
=================
1 8
2 9
3 6
4 9
5 8
Now I need to compare like this a_zone, a_address = p_zone, p_address or not.
I do not need to compare only a_zone with only p_zone or only a_address with only p_address. Rather, I need to compare the whole data combination. for my above example, I need to compare 18 with 18 [a_zone,a_address WITH p_zone, p_address ]
I'm stuck with it, and really need help. Please suggest me....:)
You haven't specified what data you wish to return so I have assumed a simple join.
Unless I am mis understandng your query I do not think that you need a union I think that you can do this with a single join:
SELECT *
FROM table_1 JOIN table_2
WHERE (table_1.a_zone = table_2.p_zone) && (table_1.a_address = table_2.p_address);
This returns:
If I understand correctly, can't you just do two nested while loops like so:
$query1 = get a_zone and a_address from table_1;
$query2 = get p_zone and p_address from table_2;
while($row = mysql_fetch_array($query1)) {
$a_zone = $row['a_zone'];
$a_address = $row['a_address'];
while($row = mysql_fetch_array($query2)) {
if($a_zone == $row['p_zone'] && $a_address == $row['p_address']) {
do_something;
}
}
}
You can start with a query like this:
SELECT *
FROM table_1 left join table_2
on table_1.a_zone = table_2.p_zone
and table_1.a_address = table_2.p_address
UNION
SELECT *
FROM table_1 right join table_2
on table_1.a_zone = table_2.p_zone
and table_1.a_address = table_2.p_address
And then you can add some conditions, like this:
SELECT *
FROM table_1 left join table_2
on table_1.a_zone = table_2.p_zone
and table_1.a_address = table_2.p_address
WHERE table_2.p_id is null or table_1.a_id <> table_2.p_id
UNION
SELECT *
FROM table_1 right join table_2
on table_1.a_zone = table_2.p_zone
and table_1.a_address = table_2.p_address
WHERE table_1.p_id is null or table_1.a_id <> table_2.p_id
But that depends on how do you need to compare the tables.