i have this working query
Sum(`sales`.`quantity`) AS totquantity,
`transactions`.`price` AS price,
Sum(`sales`.`quantity`) * `transactions`.`price` AS grantot
from (`sales` join `transactions` on((`transactions`.`idtransaction` = `sales`.`idtransaction`)))
where ((`sales`.`createon` > '01/01/2017') and (`sales`.`createon` < 'now()'))
group by `sales`.`idtransaction`
but it would be usefully to consult to create this view
select `products`.`idproduct` AS `idproduct`,`transactions`.`idtransaction` AS
`idtransaction`,`transactions`.`idline` AS `idline`,
`products`.`name` AS `name`,`products`.`code` AS `code`,`transactions`.`price` AS `price`,`sales`.`quantity` AS `quantity`,`sales`.`createon` AS `createon`
from (`sales` left join (`transactions` left join `products` on((`products`.`idproduct` = `transactions`.`idproduct`))) on((`transactions`.`idtransaction` = `sales`.`idtransaction`)))
and make a query on the view like
select * from myview where `sales`.`createon` > '01/01/2017' and `sales`.`createon` < 'now()'
now my question is are the two result the same?
thx in advance
Your original query uses two tables and full joins.
However, the view has already three tables and left joins.
That’s enough to conclude there is no guarantee they produce the same result in general.
You can provide more precise inputs to get more precise answer.
Related
I am trying to convert this query:
SELECT
pdd.pedinte_id, pdd.data, pdd.situacao as Situacao, pdd.valor_total, pdd.qtd_etiquetas,
(
SELECT count(pdi.envio_id)
FROM pedinte_item pdi
INNER JOIN envios env ON
pdi.envio_id = env.envio_id
WHERE
pdi.pedinte_id = pdd.pedinte_id AND
env.Situacao = 2
) AS TemErros
FROM pedinte pdd
left join user usr on
usr.user_id = pdd.user_id
WHERE pdd.user_id IS NOT NULL AND pdd.pedinte_id IS NOT NULL;
to CakePhp:
removed code, maybe very wrong.
Without success.
I have 4 tables:
pedinte (pdd)
pedinte_item (pdi)
envios (env)
user (usr)
pedinte > pedinte_item > envios (count)
Cant believe, harder to do the query builder than the mysql code.
(This does not address the CakePHP question, but too long for a Comment)
(Subqueries are not always "bad".)
These indexes may help performance:
usr: INDEX(user_id)
pdi: INDEX(pedinte_id, envio_id)
env: INDEX(Situacao, envio_id)
When adding a composite index, DROP index(es) with the same leading columns.
That is, when you have both INDEX(a) and INDEX(a,b), toss the former.
So I'm trying to implement a JOIN in my PHP but I don't know how to include the WHERE clause with JOIN in my query.
I'm trying to do:
SELECT SpecialFacts.ConservationStatus, SpecialFacts.Reproduction, SpecialFacts.Length, Habitat.Type, Habitat.located
FROM SpecialFacts
INNER JOIN Habitat ON SpecialFacts.SpeciesID=Habitat.SpeciesID
WHERE SpeciesID="G. cuvier"
Basically I'm trying to make sure the join happens on the tables where the SpeciesID is G. cuvier but everything I have tried so far doesn't work and the error it is giving me now is "Column SpeciesID in where clause is ambiguous".
Here is my relevant PHP code:
<?php
include 'connect.php';
$result = mysqli_query($connect,"SELECT SpecialFacts.ConservationStatus, SpecialFacts.Reproduction, SpecialFacts.Length, Habitat.Type, Habitat.located FROM SpecialFacts INNER JOIN Habitat ON SpecialFacts.SpeciesID=Habitat.SpeciesID WHERE SpeciesID='G. cuvier'") or die("fail" . mysqli_error($connect));
$i = 0;
while($row = mysqli_fetch_array($result))
{
echo $row[$i];
$i = $i + 1;
}
Column SpeciesID exists in both tables, so it doesn't know which need to be compared to value given as G. cuvier. As you are writing every column name as table name with dot(.), the same should be in where condition column SpecialFacts.SpeciesID = "G. cuvier".
So query should be like:
SELECT SpecialFacts.ConservationStatus, SpecialFacts.Reproduction, SpecialFacts.Length, Habitat.Type, Habitat.located
FROM SpecialFacts
INNER JOIN Habitat ON SpecialFacts.SpeciesID=Habitat.SpeciesID
WHERE SpecialFacts.SpeciesID="G. cuvier"
It's not giving you that error because you're using WHERE incorrectly. It's giving you that error because there are multiple tables in your query that have a column with that name, hence the "ambiguous". You just need to disambiguate it by adding the table name to the identifier.
WHERE SpecialFacts.SpeciesID="G. cuvier"
or
WHERE Habitat.SpeciesID="G. cuvier"
Since you're inner joining the tables on that column, either table should work for the WHERE clause. I would suggest using the smaller table for performance reasons, but honestly I'm not 100% certain if it will matter or not. You can do EXPLAIN on each one to see how they compare.
Use below query instead
SELECT SpecialFacts.ConservationStatus, SpecialFacts.Reproduction, SpecialFacts.Length, Habitat.Type, Habitat.located
FROM SpecialFacts INNER JOIN Habitat
ON SpecialFacts.SpeciesID=Habitat.SpeciesID
WHERE SpecialFacts.SpeciesID='G. cuvier'
I have used single quote and used column name with table name.
I have two databases and I am trying to compare two tables. My code does not seem to be working, not sure what I am doing wrong.
Here is the code.
<?php
include 'connection.php';
/*
* This code compares between two tables
*/
//SQL call
$getData = $connection->prepare("SELECT `CustomerCity` FROM `auth` LEFT JOIN `tb_data.cobs.city` WHERE `CustomerCity` = `tb_data.cobs.city` LIMIT 3");
$getData->execute();
$gotData = $getData->fetchAll(PDO::FETCH_ASSOC);
print_r($gotData);
In my database I have two tables, on is cobs, the other is tb_data. tb_data has a table called cobs and auth is a table within a database called d_data. Both of these tables have a city column. I need get every record in auth that has a city that matches in the cobs table.
That looks like the query is using a mixture of explicit join syntax with obsolescent syntax for the join using the WHERE clause for the join conditions.
If so try:-
SELECT CustomerCity
FROM auth
LEFT JOIN tb_data.cobs
ON auth.CustomerCity = cobs.city
LIMIT 3
Others have pointed out that your query is wrong, but have not provided a correct answer. This is what you are likely looking for:
SELECT `auth.CustomerCity` FROM `auth`
LEFT JOIN `tb_data.cobs` ON `tb_data.cobs.city` = `auth.CustomerCity`
LIMIT 3
Try this :
Select *.auth, *.cobs from auth join cobs on auth.city = cobs.city limit 3
The query is incorrect, you need to specify the link betweeen the tables auth and tb_data.cobs.city. For example:
SELECT
*
FROM
FOOTABLE FOO
LEFT JOIN
BARTABLE BAR ON BAR.FOO_ID FOO.ID = -- here goes the link between them
WHERE
...
Working with Symfony 2 and Doctrine, I'm searching for a way to select every rows having the max value in a specific column.
Right now, I'm doing it in two queries:
One to get the max value of the column in the table
Then I select rows having this value.
I'm sure this can be done with one query.
Searching, I have found this answer in a thread, that seems to be what I am searching for, but in SQL.
So according to the answer's first solution, the query I'm trying to build would be something like that:
select yt.id, yt.rev, yt.contents
from YourTable yt
inner join(
select id, max(rev) rev
from YourTable
group by id
) ss on yt.id = ss.id and yt.rev = ss.rev
Does anybody know how to make it in Doctrine DQL?
For now, here is the code for my tests (not working):
$qb2= $this->createQueryBuilder('ms')
->select('ms, MAX(m.periodeComptable) maxPeriode')
->where('ms.affaire = :affaire')
->setParameter('affaire', $affaire);
$qb = $this->createQueryBuilder('m')
->select('m')
//->where('m.periodeComptable = maxPeriode')
// This is what I thought was the most logical way of doing it:
->innerJoin('GAAffairesBundle:MontantMarche mm, MAX(mm.periodeComptable) maxPeriode', 'mm', 'WITH', 'm.periodeComptable = mm.maxPeriode')
// This is a version trying with another query ($qb2) as subquery, which would be the better way of doing it for me,
// as I am already using this subquery elsewhere
//->innerJoin($qb2->getDQL(), 'sub', 'WITH', 'm.periodeComptable = sub.maxPeriode')
// Another weird try mixing DQL and SQL logic :/
//->innerJoin('SELECT MontantMarche mm, MAX(mm.periodeComptable) maxPeriode ON m.periodeComptable = mm.maxPeriode', 'sub')
//->groupBy('m')
->andWhere('m.affaire = :affaire')
->setParameter('affaire', $affaire);
return $qb->getQuery()->getResult();
The Entity is GAAffairesBundle:MontantMarche, so this code is in a method of the corresponding repository.
More generally, I'm learning about how to handle sub-queries (SQL & DQL) and DQL syntax for advanced queries.
Thx!
After some hours of headache and googling and stackOverflow readings...
I finally found out how to make it.
Here is my final DQL queryBuilder code:
$qb = $this->createQueryBuilder('a');
$qb2= $this->createQueryBuilder('mss')
->select('MAX(mss.periodeComptable) maxPeriode')
->where('mss.affaire = a')
;
$qb ->innerJoin('GAAffairesBundle:MontantMarche', 'm', 'WITH', $qb->expr()->eq( 'm.periodeComptable', '('.$qb2->getDQL().')' ))
->where('a = :affaire')
->setParameter('affaire', $affaire)
;
return $qb->getQuery()->getResult();
For me when i trying to make a subquery i make:
->andWhere($qb->expr()->eq('affaire', $qb2->getDql()));
To achieve this using pure DQL and without use of any aggregate function you can write doctrine query as
SELECT a
FROM GAAffairesBundle:MontantMarche a
LEFT JOIN GAAffairesBundle:MontantMarche b
WITH a.affaire = b.affaire
AND a.periodeComptable < b.periodeComptable
WHERE b.affaire IS NULL
ORDER BY a.periodeComptable DESC
The above will return you max record per group (per affaire)
Expalnation
The equivalent SQL for above DQL will be like
SELECT a.*
FROM MontantMarche a
LEFT JOIN MontantMarche b
ON a.affaire = b.affaire
AND a.periodeComptable < b.periodeComptable
WHERE b.affaire IS NULL
ORDER BY a.periodeComptable DESC
Here i assume there can be multiple entries in table e.g(MontantMarche) for each affaire, so here i am trying to do a self join on affaire and another tweak in join is i am trying to join only rows from right table(b) where a's periodeComptable < b's periodeComptable, So the row for left table (a) with highest periodeComptable will have a null row from right table(b) thus to pick the highest row per affaire the WHERE right table row IS NULL necessary.
Similarly using your posted sample query with inner join can be written as
select yt.id, yt.rev, yt.contents
from YourTable yt
left join YourTable ss on yt.id = ss.id and yt.rev < ss.rev
where ss.rev is null
Hope it makes sense
I have an issue getting data from three tables, which I want to return using one query.
I've done this before using a query something like this one:
$query = mysql_query("SELECT
maintable.`id`,
maintable.`somedata`,
maintable.`subtable1_id`,
subtable1.`somedata`,
subtable1.`subtable2_id`,
subtable2.`somedata`
FROM
`maintable` maintable,
`subtable1` subtable1,
`subtable2` subtable2
WHERE
maintable.`somedata` = 'some_search' AND
subtable1.`id` = maintable.`subtable1_id` AND
subtable2.`id` = subtable1.`subtable2_id`
")or die(mysql_error());
The problem this time is that the extra details might not actually apply. I need to return all results that match some_search in maintable, even if there is no subtable1_id specified.
I need something that will go along the lines of
WHERE
maintable.`somedata` = 'some_search'
AND IF maintable.`subtable1_id` IS NOT NULL (
WHERE subtable1.`id` = maintable.`subtable1_id` AND
subtable2.`id` = subtable1.`subtable2_id`
)
As you will probably guess, I am not an advanced mysql user! Try as I might, I cannot get the syntax right, and I have had no luck searching for solutions on the web.
Any help much appreciated!
It seems like the basic distinction you're looking for is between an INNER JOIN and a LEFT JOIN in MySQL.
An INNER JOIN will require a reference between the two tables. There must be a match on both sides for the row to be returned.
A LEFT JOIN will return matches in both rows, like an INNER, but it will also returns rows from your primary table even if no rows match in your secondary tables -- their fields will be NULL.
You can find example syntax in the docs.
If I got this right, you need to use MySQL LEFT JOIN. Try this:
SELECT
m.id,
m.somedata,
m.subtable1_id,
s1.somedata,
s1.subtable2_id,
s2.somedata
FROM
maintable m
LEFT JOIN
subtable1 s1
ON
m.subtable1_id = s1.id
LEFT JOIN
subtable2 s2
ON
s1.subtable2_id = s2.id
WHERE
m.somedata = 'some search'
This will return the data of maintable even if there's no equivalent data in subtable1 or 2 OR data of maintable and subtable1 if there's no equivalent data in subtable2.
How about this:
WHERE
maintable.`somedata` = 'some_search'
AND (maintable.`subtable1_id` IS NULL OR (
subtable1.`id` = maintable.`subtable1_id` AND
subtable2.`id` = subtable1.`subtable2_id` )
)
Keep in mind that this will result in a cross product of subtable1 and subtable2 with maintable when subtable1_id is NULL.