I have problem with innerJoin.
Two tables range and product:
table range
id
parent_id
category_id
table product
id
range_id
the query must join range.id with range2.chidren only level 1 and range, range2 with product
ex:
range.id = product.range_id or range2.id = product.range_id:
I want something like :
INNER JOIN product p1_ ON p0_.id = p1_.range_id or p4_.id = p1_.range_id
with doctrine when I write :
->innerJoin('r.products', 'p', Expr\Join::WITH, 'r.id = p.range or rp.id = p.range ')
I got :
INNER JOIN product p1_ ON p0_.id = p1_.range_id AND (p0_.id = p1_.range_id OR p4_.id = p1_.range_id)
someone have solution
Related
Trying to join 4 - 5 tables at once as of wanted to grab multiple data which is stored in 5 tables on in 5th table i am trying to count total number of players that have been joined the tournament this is working fine but the main problem which I am facing here is when there is not data in the main table it still return me 1 row with all fields as null except total players showing 0 as it shown not return any rows can anyone help em out below is my query
$getTournamentData = $this->db->select('tournament.*, tournament_meta.meta_title, tournament_meta.meta_description, categories.title AS category, categories.slug AS category_slug, games.game_name, games.slug AS game_slug, count(tournament_players.id) AS total_players');
$getTournamentData = $this->db->join('categories', 'categories.id = tournament.category_id');
$getTournamentData = $this->db->join('games', 'games.game_id = tournament.game_id');
$getTournamentData = $this->db->join('tournament_meta', 'tournament_meta.post_id = tournament.id');
$getTournamentData = $this->db->join('tournament_players', 'tournament_players.tournamentID = tournament.id', 'left');
$dataCond['created_by'] = $this->session->userdata('user_id');
if($id != null) {
$dataCond['tournament.id'] = $id;
}
$getTournamentData = $this->db->where($dataCond);
$getTournamentData = $this->db->get('tournament');
so in return total_players are showing 0 and rest all is null because no data is insterted in the table yet show it should not return any data from the database
You're mixing an aggregate function (count()) with plain column names in your SELECT clause and that is giving unexpected results.
See: Why can't you mix Aggregate values and Non-Aggregate values in a single SELECT?
You can fix this by adding a GROUP BY clause with all of the column names from the SELECT clause, except for the column name that has the count() on it. Be sure to fully type out all of the column names for the tournament.* in the GROUP BY, so use tournament.id, tournament.category_id, tournament.game_id etc instead:
SELECT tournament.*, tournament_meta.meta_title, tournament_meta.meta_description, categories.title AS category, categories.slug AS category_slug, games.game_name, games.slug AS game_slug, count(tournament_players.id) AS total_players
FROM tournament
JOIN categories ON categories.id = tournament.category_id
JOIN games ON games.game_id = tournament.game_id
JOIN tournament_meta ON tournament_meta.post_id = tournament.id
JOIN tournament_players ON tournament_players.tournamentID = tournament.id
GROUP BY
tournament.id, tournament.category_id, tournament.game_id,
-- add other tournament colums here --
tournament_meta.meta_title, tournament_meta.meta_description, categories.title, categories.slug, games.game_name, games.slug
In CodeIgniter (3) this would translate to:
$this->db->select('tournament.*, tournament_meta.meta_title, tournament_meta.meta_description, categories.title AS category, categories.slug AS category_slug, games.game_name, games.slug AS game_slug, count(tournament_players.id) AS total_players');
$this->db->from('tournament');
$this->db->join('categories', 'categories.id = tournament.category_id');
$this->db->join('games', 'games.game_id = tournament.game_id');
$this->db->join('tournament_meta', 'tournament_meta.post_id = tournament.id');
$this->db->join('tournament_players', 'tournament_players.tournamentID = tournament.id');
$this->db->group_by('tournament.id, tournament.category_id, tournament.game_id,
/* add other tournament columns here */
tournament_meta.meta_title, tournament_meta.meta_description, categories.title, categories.slug, games.game_name, games.slug');
Alternatively you can use a subselect, in which case you can remove the join to the tournament_players table:
SELECT tournament.*, tournament_meta.meta_title, tournament_meta.meta_description, categories.title AS category, categories.slug AS category_slug, games.game_name, games.slug AS game_slug, (
SELECT count(id)
FROM tournament_players
WHERE tournament_players.tournamentID = tournament.id) AS total_players
FROM tournament
JOIN categories ON categories.id = tournament.category_id
JOIN games ON games.game_id = tournament.game_id
JOIN tournament_meta ON tournament_meta.post_id = tournament.id
Use with $this->db->query() in CodeIgniter.
I haven't tested these queries obviously, so there may be errors.
Hopefully this'll help you get started.
I need to add a field in one of our query. I'm nt a PHP programmer buy I can get my way around a little. The query is:
if (_QUERYSTRING_) {
switch ($intMode) {
case -1:
$result = mysqli_query($mysql,"
SELECT orders.id,
orders_addresses.strlastname,
orders_addresses.strfirstname,
orders_addresses.intprovince,
9 AS intmode,
Date(orders.dtimeorder) AS datepayment,
orders_costs.dbltotal AS dblamount,
orders_notes.strcod AS strtxn,
0 AS dblfee,
shipping_postalservices.strtracking"._LANG_." as strtrackingurl,
'À recevoir' AS strmode,
NULL AS strvendor
FROM orders
JOIN orders_costs
ON orders_costs.id = orders.id
JOIN orders_addresses
ON orders_addresses.id = orders.id
JOIN orders_notes
ON orders_notes.id = orders.id
JOIN shipping_postalservices
ON shipping_postalservices.id = orders_costs.intpostalservice
WHERE date(orders.dtimeorder) BETWEEN '".date("Y-m-d",$timeStart)."' AND '".date("Y-m-d",$timeEnd)."'
AND orders.boolshipped = 1
AND orders.boolcanceled = 0
AND orders_costs.boolcod = 1
AND orders_costs.dbltotal > 0
AND NOT EXISTS
(
SELECT *
FROM orders_payments
WHERE orders_payments.intorder = orders.id
AND orders_payments.intmode = 9
AND orders_payments.dblamount > 0)
GROUP BY orders.id
ORDER BY orders.dtimeorder,
orders.id");
break;
default:
$result = mysqli_query($mysql,"
SELECT orders.id,
orders_addresses.strlastname,
orders_addresses.strfirstname,
orders_addresses.intprovince,
orders_payments.intmode,
Date(orders_payments.dtimepayment) AS datepayment,
orders_payments.dblamount,
orders_payments.strtxn,
orders_payments.dblfee,
shipping_postalservices.strtracking"._LANG_." as strtrackingurl,
payments.strname"._LANG_." AS strmode,
payments.strvendor
FROM orders_payments
JOIN orders
ON orders.id = orders_payments.intorder
JOIN orders_costs
ON orders_costs.id = orders.id
JOIN orders_addresses
ON orders_addresses.id = orders.id
JOIN shipping_postalservices
ON shipping_postalservices.id = orders_costs.intpostalservice
LEFT JOIN payments
ON payments.id = orders_payments.intmode
WHERE date(orders_payments.dtimepayment) BETWEEN '".date("Y-m-d",$timeStart)."' AND '".date("Y-m-d",$timeEnd)."'".(!empty($intMode) ? "
AND orders_payments.intmode = '".$intMode."'" : NULL)."
GROUP BY orders.id,
orders_payments.intpayment
ORDER BY orders_payments.dtimepayment,
orders.id");
break;
}
The field that needs to be added is orders_addresses.intProvince so it can be displayed in the results. I tried to understand a little but I guess it's a little more complicated than I thought. It does display the province, which are numbers. My question would be, how do I "translate" those numbers by the actual names so it displays "Ontario" instead of 9? The name of the provinces are in another table called Province.
You will need to add another JOIN:
JOIN Province ON orders_addresses.intprovince = Province.x
And in the SELECT part, replace orders_addresses.intprovince by Province.y
where
x = column in table Province that holds the province id
y = column in table Province that holds the province name
Hello I have this problem and can't find a solution:
I have 4 tables with same structure for example as follows:
Table 1: Result
Table 2: Store 1
Table 3: Store 2
Table 4: Store 3
Tables fields: ID - Code - Name - Value
I need a query to read the "Value" for each specific record from tables (Store 1 - Store 2 - Store 3) and calculate the average and save it in table (Result)...
and go on for the next record until it's done.
Note: I'm using PHP and MySQL...
Thanks in advanced...
SELECT
result.id,
result.`code`,
result.`name`,
result.value,
term1.value,
term2.value,
term3.value
FROM result
INNER JOIN store1 ON result.`code` = store1.`code`
INNER JOIN store2 ON result.`code` = store2.`code`
INNER JOIN store3 ON result.`code` = store3.`code`
WHERE result.`code` = 123456
ORDER BY result.serial ASC
The average is just the sum of the values divided by the number of values (3), this is grade school arithmetic.
UPDATE result AS r
JOIN store1 AS s1 ON s1.code = r.code
JOIN store2 AS s2 ON s2.code = r.code
JOIN store3 AS s3 ON s3.code = r.code
SET r.value = (s1.value+s2.value+s3.value)/3
To do lots of columns, you can generate the SQL in PHP:
$cols = array('col1', 'col2', 'col3', ...);
$sets = implode(', ', array_map(function($col) {
return "r.$col = (s1.$col + s2.$col + s3.$col)/3";
}, $cols));
$sql = "UPDATE result AS r
JOIN store1 AS s1 ON s1.code = r.code
JOIN store2 AS s2 ON s2.code = r.code
JOIN store3 AS s3 ON s3.code = r.code
SET $sets";
If you're using PHP before 5.3.0, you can define a named function to call it with array_map
function make_assignment($col) {
return "r.$col = (s1.$col + s2.$col + s3.$col)/3";
}
$sets = implode(', ', array_map('make_assignment', $cols));
You can create views in MySQL for this. Then there will not need any for this. View is a virtual table. On every change in any table it will automatically updated. You don't need any query
create view result as select t1.code as code,(t1.value+t2.value+t3.value)/3 as value from `testcake`.`test1` as t1 JOIN `testcake`.`test2` as t2 ON t1.code = t2.code JOIN `testcake`.`test3` as t3 ON t1.code = t3.code
I have structured a categories table to store Categories as well as Sub Categories.
My table Structure is:
catID (int)
catType (varchar 4)
parentID (int)
catName (varchar 50)
sOrder (int)
How to do following subquery with Eloquent.
SELECT c.*,
(
SELECT COUNT(*) FROM categories AS sc WHERE sc.parentID = c.catID AND sc.catType = "Sub"
) AS totalSubCategories
FROM categories AS c
WHERE c.catType = 'Root'
I have tried following but it wont work:
$rows = CategoryModel::from('categories as c')
->where('c.catType', '=', 'Root')
->paginate(20)
->select(DB::raw('c.*, (SELECT COUNT(*) FROM categories as sc WHERE sc.parentID = c.catID AND sc.catType = "Sub") AS totalCategories'));
I am getting following Error
ErrorException (E_UNKNOWN)
call_user_func_array() expects parameter 1 to be a valid callback, class 'Illuminate\Support\Collection' does not have a method 'select'
You can add an Eloquent relationship on the same table, and filter it to the right catType:
public function children() {
return $this->hasMany('Model', 'parentID')->where('catType', 'Sub');
}
This makes the item's children available as $item->children. You can get a count like so:
$count = $item->children()->count();
I have a sql query like so:
SELECT `categories`.`partnumbersafe`, `filters`.`filtername`, `filters`.`filtervalue`
FROM `products_categories` AS `categories`
LEFT OUTER JOIN `products` AS `product` ON `categories`.`partnumbersafe` = `product`.`partnumbersafe`
LEFT OUTER JOIN `products_filters` AS `filters` ON `categories`.`partnumbersafe` = `filters`.`partnumbersafe`
WHERE `categories`.`categoryid` =4
AND (`product`.`visibility` =1 OR `product`.`visibility` =2)
AND `product`.`status` =1
This gives me a result where there are multiple partnumbersafe entries (same value) with different filternames and filtervalues. For example:
partnumbersafe filtername filtervalue
123 brand toyota
123 model F5
123 type business
678 brand toyota
678 model F6
The query is generated by PHP. I also have POST values in my PHP script which hold filterdata (brand is toyota, model is F6 for example).
How can I filter these results for filtername/value pairs? I would prefer a sql query solution instead of a php solutiuon, where I can query for partnumbersafe where brand is toyota and model is F6. So that it would only retrieve partnumbersafe 123 in the above table.
The table products_filters holds all the data as represented by the table outline above.
you need to have multiple condition here. The number of record for each partnumbersafe is equal to the number of condition you supplied.
SELECT partnumbersafe
FROM...
WHERE (filterName = 'Brand' AND filtervalue = 'toyota')
OR
(filterName = 'Model' AND filtervalue = 'F6')
GROUP BY partnumbersafe
HAVING COUNT(*) = 2
SELECT
`categories`.`partnumbersafe`
FROM
`products_categories` AS `categories`
LEFT OUTER JOIN
`products` AS `product`
ON `categories`.`partnumbersafe` = `product`.`partnumbersafe`
LEFT OUTER JOIN
`products_filters` AS `filters`
ON `categories`.`partnumbersafe` = `filters`.`partnumbersafe`
WHERE
`categories`.`categoryid` = 4
AND (`product`.`visibility` =1 OR `product`.`visibility` =2)
AND `product`.`status` =1
AND
(
(`filters`.`filtername` = 'Brand' AND `filters`.`filtervalue` = 'Toyota')
OR
(`filters`.`filtername` = 'Model' AND `filters`.`filtervalue` = 'F6')
)
GROUP BY
`categories`.`partnumbersafe`
HAVING
COUNT(*) = 2
This assumes that you only need the partnumbersafe and that no filtername/filtervalue pair would ever apply to the same partnumbersafe more than once.