Symfony - doctrine createQueryBuilder multiple Joins - php

i have this query in MySQL and i want to apply into doctrine
SELECT * FROM ads_list AS al LEFT JOIN (ads_category AS ac, ads_category_main AS acm) ON (ac.id = al.category_id AND ac.parent_cat_id = acm.id)
do you have any idea how to use this with doctrine ?
i'm using this in a Repository
parameter goes to ads_category_main
so i'm trying to select the ads_list with category and each category has a parentCategory which is stored in ads_category_main
SQL
CREATE TABLE `ads_list` (
`id` int(11) NOT NULL,
`category_id` int(11) DEFAULT NULL,
`title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`posted_at` date NOT NULL,
`post_xpr` date NOT NULL,
`agency_id` int(11) DEFAULT NULL,
`slug` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `ads_category` (
`id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`parent_cat_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `ads_category_main` (
`id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
so far i got
public function findAllP($main)
{
return $this->createQueryBuilder('pl')
->leftJoin('pl.category', 'al')
->where('al.parentCat = :pc')
->setParameter('pc', $main)
->getQuery()
->execute();
}
and how do i use the output data in a controller ?

As long as you have the entities related you could do the join like
->join/leftJoin('entity.foreign_key','alias')
if the enitities are not related you must specify the "ON" option of the join.
after that you have some ways to handle the result.
$qb->getQuery()->getResult();
$qb->getQuery()->getArrayResult();

Related

Multiple joins producing unwanted results

I'm getting weird results from my query. The numbers are way off and I can't figure out why.
Heres the table structure for the tables used in the query:
CREATE TABLE IF NOT EXISTS `bookings` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`customer_id` int(11) DEFAULT NULL,
`payment_method_id` int(11) DEFAULT NULL,
`date` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`time` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`details` text COLLATE utf8mb4_unicode_ci,
`ip` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`status` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'Complete',
`booked_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `booking_products` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`booking_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`amount` int(11) NOT NULL,
`price_subtotal` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`price_total` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `booking_services` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`booking_id` int(11) NOT NULL,
`service_id` int(11) NOT NULL,
`reservations` int(11) NOT NULL,
`price_subtotal` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`price_total` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `payment_methods` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `payment_methods_name_unique` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Here is my query:
return DB::table('bookings')
->selectRaw('payment_methods.name, count(bookings.id) as bookings, (sum(booking_services.price_subtotal) + sum(booking_products.price_subtotal)) as subtotal')
->join('booking_services', 'booking_services.booking_id', '=', 'bookings.id')
->join('booking_products', 'booking_products.booking_id', '=', 'bookings.id')
->join('payment_methods', 'payment_methods.id', '=', 'bookings.payment_method_id')
->where('bookings.status', 'Complete')
->whereBetween('bookings.booked_at', [$this->carbon_from, $this->carbon_to])
->groupBy('payment_methods.id')
->orderBy('payment_methods.name')
->get();
$this->carbon_from and $this->carbon_to are carbon objects which work fine.
I'm trying to obtain the total bookings and a sum of the price_subtotals for each payment method. It seems to be grouping the booking products/services together rather than by each payment method like I want.
Am I missing something here?
Edit: here is the query log:
select payment_methods.name,
count(bookings.id) as bookings,
(sum(booking_services.price_subtotal) + sum(booking_products.price_subtotal)) as subtotal
from `bookings`
inner join `booking_services` on `booking_services`.`booking_id` = `bookings`.`id`
inner join `booking_products` on `booking_products`.`booking_id` = `bookings`.`id`
inner join `payment_methods` on `payment_methods`.`id` = `bookings`.`payment_method_id`
where `bookings`.`status` = ? and `bookings`.`booked_at` between ? and ?
group by `payment_methods`.`id`
order by `payment_methods`.`name` asc
I guess you are getting cross product that is why you are getting wrong numbers for aggregation, what i suggest you, calculate your sum in individual sub clauses and then join these clauses with your main query like
SELECT p.name,
COUNT(DISTINCT b.id) AS bookings,
bs.price_subtotal + bp.price_subtotal AS subtotal
FROM bookings b
INNER JOIN (
SELECT booking_id, SUM(price_subtotal) price_subtotal
FROM booking_services
GROUP BY booking_id
) bs ON b.id = bs.booking_id
INNER JOIN (
SELECT booking_id, SUM(price_subtotal) price_subtotal
FROM booking_products
GROUP BY booking_id
) bp ON b.id = bp.booking_id
INNER JOIN payment_methods p ON p.id = b.payment_method_id
WHERE b.status = ?
AND b.booked_at BETWEEN ? AND ?
GROUP BY p.name
ORDER BY p.name
I have no clue how to transform/write above query using laravel's query builder/eloquent way
Try to group by payment_method_id from the bookings table:
->groupBy('bookings.payment_method_id')

Symfony DQL not executing subquery

I'm quite new to DQL and I've got a problem with subqueries.
I need to get a list of videoIDs that got added in query2 after the last execution of an optimization.
Symfony is throwing me this exception:
[Syntax Error] line 0, col -1: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got end of string.
I think the error is generated by the subquery.
Do you know why? Or do you have another way - maybe simpler - of doing this?
This is my code:
public function showOptimizable(){
$query = $this->em->createQuery('
SELECT e.videoID
FROM AppBundle:Query2 e
WHERE e.timestamp < (
SELECT MAX(o.lastOptimization)
FROM AppBundle:Optimization
)
GROUP BY e.videoID HAVING COUNT(e.videoID) < 3
ORDER BY e.videoID DESC
');
return $query->getResult();
}
This is query2:
CREATE TABLE `query2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`query` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`timestamp` datetime NOT NULL,
`ip` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`uAgent` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`videoID` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`trackTitle` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`present` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_2D293848A5D6E63E` (`timestamp`)
)
And this is optimization:
CREATE TABLE `optimization` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`lastOptimization` datetime NOT NULL,
`optimizedElements` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
The alias "o" is missing. Try this:
(
SELECT MAX(o.lastOptimization)
FROM AppBundle:Optimization o
)

execute sql query in php doesn't work ,but the query work in phpmyadmin

i have my database sql query file and i wanna run it in php by the code below
$query = file_get_contents('./sqlquery.txt');
print $query;
$conn->query($query);
but it return this error
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TABLE IF NOT EXISTS `ads` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ur' at line 2
i copied the print output in to the phpmyadmin and everything work well, what's wrong here?
my sql query is the this
DROP TABLE IF EXISTS `ads`;
CREATE TABLE IF NOT EXISTS `ads` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(300) NOT NULL,
`path` varchar(200) NOT NULL,
`width` int(11) NOT NULL,
`height` int(11) NOT NULL,
`priority` int(11) NOT NULL,
`adsalter` varchar(200) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`adstitle` varchar(200) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;
DROP TABLE IF EXISTS `comment`;
CREATE TABLE IF NOT EXISTS `comment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(120) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`comment` text CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`contentid` int(11) NOT NULL,
`parentid` int(11) NOT NULL DEFAULT '0',
`date` varchar(250) NOT NULL,
`haschild` int(1) NOT NULL DEFAULT '0',
`visible` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
DROP TABLE IF EXISTS `files`;
CREATE TABLE IF NOT EXISTS `files` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`size` int(14) NOT NULL,
`type` varchar(50) NOT NULL,
`newsid` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
DROP TABLE IF EXISTS `frgpss`;
CREATE TABLE IF NOT EXISTS `frgpss` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(100) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`ip` varchar(31) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL,
`token` varchar(27) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`date` int(15) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
DROP TABLE IF EXISTS `news`;
CREATE TABLE IF NOT EXISTS `news` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`titrimage` varchar(100) NOT NULL,
`titr` varchar(100) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`titralter` varchar(160) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`newsshurt` varchar(200) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`text` text CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`keywords` text CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`description` text CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`author` varchar(200) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`branch` int(11) NOT NULL,
`date` varchar(160) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`visible` int(1) NOT NULL DEFAULT '0',
`visited` int(11) NOT NULL DEFAULT '0',
`titrtitle` varchar(200) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
DROP TABLE IF EXISTS `signup`;
CREATE TABLE IF NOT EXISTS `signup` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`family` varchar(50) NOT NULL,
`email` varchar(80) NOT NULL,
`gender` varchar(50) NOT NULL,
`username` varchar(80) NOT NULL,
`picture` varchar(80) NOT NULL,
`password` varchar(60) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(60) NOT NULL,
`lastname` varchar(60) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(40) NOT NULL,
`userregistereddate` varchar(60) NOT NULL,
`key` varchar(60) NOT NULL,
`type` varchar(20) NOT NULL,
`userphoto` varchar(50) NOT NULL,
`usergroup` varchar(300) NOT NULL,
`ipaddress` text NOT NULL,
`telnumber` varchar(14) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
you're executing multiple queries here, it won't work simply, I'm pretty sure that in query function($conn->query($query);) you're using mysql_query() or mysqli_query(), but you'll have to do is to use mysqli_multi_query() instead. Have a look here at docx
$con = mysqli_connect($host, $user, $pass, $db) OR die(mysqli_error($con));
$query = file_get_contents('./sqlquery.txt');
mysqli_multi_query($con, $query);
mysqli_close($con);
Hope this will help you
Note: Assuming that all queries are working fine while executing in PHPMyAdmin.

Is it possible to set 2 separate unique fields using Redbean ORM

I am using the redbeanPHP ORM and mysql. I have the following table:
CREATE TABLE `mast` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`note` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`geolocation` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`location` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`zip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`state` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`app` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UQ_84a93b55f688c94f73092dba1b9590c41a92cbf5` ('app')
) ENGINE=InnoDB AUTO_INCREMENT=98 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
I want to insert records into the 'mast' table providing they are unique with respect to both of the 2 fields listed above. In other words if either 'geolocation' or 'app' is a duplicate, I don't want to insert the associated record.
I am using following php code to create the 2 unique fields:
$mast= R::dispense('mast');
$mast->setMeta("buildcommand.unique" , array(array('geolocation')));
$mast ->import($resultsarray);
$mast->setMeta("buildcommand.unique" , array(array('app')));
$id = R::store($mast); // DUMMY BEAN
A unique index is only being created for the 'app' field . Is there a way to set them both as unique in redbean?
From the documentation it should work like the following:
$mast = R::dispense('mast');
$mast->setMeta("buildcommand.unique.0", array('geolocation', 'app'));
$mast->import($resultsarray);
$id = R::store($mast);
In your code you just overwrote the value for build command.unique.

Selecting rows that corresponds from other table

I have a product table that stores all products. Also I have a production table that stores productions.
I am using CodeIgniter and datamapper ORM.
Here is tables:
CREATE TABLE IF NOT EXISTS `products` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`kod_stok` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`kod_lokal` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`kod_firma` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`firma` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`fabrika` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`proje` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`tanim` mediumtext COLLATE utf8_unicode_ci,
`saatlik_uretim` int(11) NOT NULL,
`status` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `kod_lokal` (`kod_lokal`),
KEY `kod_firma` (`kod_firma`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
CREATE TABLE IF NOT EXISTS `productions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fabrika` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`board_no` int(11) NOT NULL,
`date` int(11) DEFAULT NULL, // Unix Timestamp
`operator_id` int(11) DEFAULT NULL,
`product_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `product` (`product_id`),
KEY `date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
I am trying to get count of production of given day. But not all products, producting everyday. I need to exlude the products that has 0 count.
$p = new Product();
$p->include_related_count('production');
$p->get();
And I want to add a date interval to production.
Basicly, I want to get all product's production count within a given day.
How can I do that?
Thank you for any advices.
Not sure about codeigniter details, but the following SQL query will generate a production list per day.
To get today's production:
$query = $this->db->query("
SELECT
a.count(*) as produced
, a.product_id
, b.kod_stok as productname
FROM productions a
INNER JOIN products b ON (a.product_id = b.id)
WHERE FROM_UNIXTIME(a.date) = CURDATE()
GROUP BY TO_DAYS(FROM_UNIXTIME(a.date)), a.product_id
");
To get last 7 days production
$query = $this->db->query("
SELECT
a.count(*) as produced
, a.product_id
, b.kod_stok as productname
FROM productions a
INNER JOIN products b ON (a.product_id = b.id)
WHERE FROM_UNIXTIME(a.date)
BETWEEN DATE_SUB(CURDATE(),INTERVAL 7 DAY) AND CURDATE()
GROUP BY TO_DAYS(FROM_UNIXTIME(a.date)), a.product_id
");

Categories