how to use sql query in sql query - php

I have two tables:
table category(cat_id,category)
table category_details(cat_id,id,...)
I have sql code like bellow:
$sql=mysql_query("select * from category");
while($rows=mysql_fetch_array($sql)){
$id_count=$rows['cat_id'];
$sql1=mysql_query("select * from category_details where cat_id='$id_count'");
$count=mysql_num_rows($sql1);
}
Can I use like this?

Use JOIN.
Example
SELECT * FROM category LEFT JOIN
category_details ON category_details.cat_id = category.cat_id;
above query will return all the category and associated category detail.
OP Comment Response
SELECT c.name,
IFNULL(sub_c.total, 0) num
FROM category c
LEFT JOIN ( SELECT COUNT(*) total, cat_id
FROM category_details
GROUP BY cat_id
) sub_c ON (sub_c.cat_id = c.cat_id);
Complete Code
<?php
$query = "SELECT c.name,
IFNULL(sub_c.total, 0) num
FROM products_category c
LEFT JOIN ( SELECT COUNT(*) total, cat_id
FROM product
GROUP BY cat_id
) sub_c ON (sub_c.cat_id = c.id)";
$result = mysql_query($query)or die(mysql_error());
echo "<table><tr><td>NameCount</td></tr>";
while($row = mysql_fetch_assoc($result))
{
echo "<tr><td>".$row['name']."(".$row['num'].")"."</td></tr>";
}
echo "</table>";
?>
MySQL Table
ProductCategory Table
CREATE TABLE IF NOT EXISTS `products_category` (
`id` int(11) NOT NULL,
`name` varchar(200) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `products_category`
--
INSERT INTO `products_category` (`id`, `name`) VALUES
(1, 'Erasmus'),
(2, 'Preston'),
(3, 'Ulric'),
(4, 'Gray'),
(5, 'Joseph'),
(6, 'Merrill'),
(7, 'Alan'),
(8, 'Jeremy'),
(9, 'Solomon'),
(10, 'Andrew'),
(11, 'Galvin'),
(12, 'Craig'),
(13, 'Cameron'),
(14, 'Omar'),
(15, 'Addison');
Product Table
CREATE TABLE IF NOT EXISTS `product` (
`id` int(11) NOT NULL,
`name` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`cat_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `product`
--
INSERT INTO `product` (`id`, `name`, `cat_id`) VALUES
(1, 'Wesley', 1),
(2, 'Graiden', 2),
(3, 'Cruz', 5),
(4, 'Hayden', 5),
(5, 'Kennedy', 6),
(6, 'Uriah', 8),
(7, 'Alan', 8),
(8, 'Cade', 1),
(9, 'Ryan', 5),
(10, 'Brody', 7);
Above will output
Erasmus(2)
Preston(1)
Ulric(0)
Gray(0)
Joseph(3)
Merrill(1)
Alan(1)
Jeremy(2)
Solomon(0)
Andrew(0)
Galvin(0)
Craig(0)
Cameron(0)
Omar(0)
Addison(0)

Are you looking to use COUNT with GROUP BY:
select c.cat_id, c.cat_name, count(cd.*)
from category c
left join category_details cd
on c.cat_id = cd.cat_id
group by c.cat_id, c.cat_name
This will return each category with the count of category_details associated with it. Using LEFT JOIN will return all categories -- replace with an INNER JOIN if you want only those with details.

Related

Mysql get multiple counts from stats database

I need to get unique counts along with country counts and sum rate for every user
I have come up with this basic design for database where uid is user id
DROP TABLE IF EXISTS `stats`;
CREATE TABLE IF NOT EXISTS `stats` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`uid` int(5) UNSIGNED NOT NULL,
`country` int(3) UNSIGNED NOT NULL,
`ip` int(10) UNSIGNED NOT NULL,
`date` int(10) UNSIGNED NOT NULL,
`timestamp` int(10) UNSIGNED NOT NULL,
`rate` int(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `stats`
(`id`, `uid`, `country`, `ip`, `date`, `timestamp`, `rate`) VALUES
(1, 1, 10, 1111111111, 2222222222, 3333333333, 100),
(2, 1, 10, 1111111112, 2222222222, 3333333333, 100),
(3, 2, 10, 1111111111, 2222222222, 3333333333, 100),
(4, 1, 10, 1111111114, 2222222223, 3333333333, 100),
(5, 1, 11, 1111111112, 2222222223, 3333333333, 100),
(6, 1, 10, 1111111111, 2222222223, 3333333333, 100);
And this is the query I am using to fetch daily counts
$query="
SELECT `uid`,
COUNT(DISTINCT `ip`)AS `count`,
`country`,
SUM(`rate`) AS `sum`,
`date`
FROM `stats`
GROUP BY `uid`, `date`
";
$result=mysqli_query($connection, $query) or trigger_error(mysqli_error($connection), E_USER_ERROR);
while($row = mysqli_fetch_assoc($result)){
echo 'userid:'.$row['uid'].' count:'.$row['count'].' country:'.$row['country'].' sum:'.$row['sum'].' date:'.$row['date'].'<br>';
};
I am getting this result
userid:1 count:2 country:10 sum:200 date:2222222222
userid:1 count:3 country:10 sum:300 date:2222222223
userid:2 count:1 country:10 sum:100 date:2222222222
Expected result
userid:1 count:2 country:10=>2 sum:200 date:2222222222
userid:1 count:3 country:10=>2, 11=>1 sum:300 date:2222222223
userid:2 count:1 country:10=>1 sum:100 date:2222222222
I guess I need something like SELECT DISTINCT country FROM stats to get country counts in main query.
Please see and suggest any possible way to do this.
Thanks
You can use subquery to achieve this:
SELECT
t.uid,
SUM(t.count) AS count,
GROUP_CONCAT(CONCAT(t.country, ' => ', t.views) SEPARATOR ', ') AS country,
SUM(t.sum) as sum,
t.date
FROM (
SELECT
s.uid,
COUNT(DISTINCT s.ip) AS count,
s.country,
COUNT(s.country) as views,
SUM(s.rate)AS sum,
s.date
FROM stats s
GROUP BY uid, date, country
) AS t
GROUP BY
t.uid,
t.date
Also available at sqlfiddle.
SUM needs a column and you gave string 'rate' in it, remove the ' from rate column name try this,
SELECT
COUNT(DISTINCT `ip`)AS `count`,
`country`,
SUM(rate) AS `sum`
FROM `stats`
GROUP BY `uid`, `date`
You will have to add country into the GROUP condition too:
SELECT
COUNT(DISTINCT `ip`) AS `count`,
`country`,
COUNT(`country`) as `countryViewsByUser`, -- added
SUM(`rate`)AS `sum`
FROM
`stats`
GROUP BY
`uid`,
`date`,
`country` -- added
You will just need to add country to your group by clause like below
$query="
SELECT
COUNT(DISTINCT `ip`)AS `count`,
`country`,
COUNT(DISTINCT `country`) AS country_count,
SUM(`rate`) AS `sum`
FROM `stats`
GROUP BY `country`, `uid`, `date`
";
And please you need to move away from mysqli_* functions, and take a look at PDO instead

I want select data but it doesn't work

I have a table:
CREATE TABLE IF NOT EXISTS `ccu_log` (
`id` int(15) NOT NULL AUTO_INCREMENT,
`ccu` int(10) DEFAULT NULL,
`time` time DEFAULT NULL,
`date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5626 ;
--
-- Dumping data for table `ccu_log`
--
INSERT INTO `ccu_log` (`id`, `ccu`, `time`, `date`) VALUES
(1, 0, '22:27:30', '2015-01-08'),
(2, 0, '22:29:01', '2015-01-08'),
(3, 0, '22:30:31', '2015-01-08'),
(4, 0, '22:32:01', '2015-01-08'),
(5, 3, '22:33:31', '2015-01-08'),
(6, 0, '22:35:01', '2015-01-08'),
(7, 4, '22:36:31', '2015-01-08'),
(8, 8, '22:38:01', '2015-01-09'),
(9, 5, '22:39:31', '2015-01-09'),
(10, 1, '22:41:01', '2015-01-09');
When I want select data with mysql query:
SELECT *
FROM `ccu_log`
WHERE UNIX_TIMESTAMP("date") = UNIX_TIMESTAMP('09-01-2015')
It show all rows from my table. If i user query:
SELECT * FROM `ccu_log` where UNIX_TIMESTAMP(date) = UNIX_TIMESTAMP('09-01-2015')
It doesn't return the expected results.
Any suggestions?
When the field is already of type date, you don't even need to convert to a timestamp for comparison. Just do
SELECT * FROM `ccu_log` WHERE `date`='2015-01-09'
Please try like this,
SELECT * FROM `ccu_log` where DATE_FORMAT(date,"%d-%m-%Y") = '09-01-2015';

get the count of field and group concat

table structure is as follows
-- Table structure for table category
CREATE TABLE `category` (
`cat_id` int(10) NOT NULL auto_increment,
`heading` varchar(255) NOT NULL,
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `category` (`cat_id`, `heading`) VALUES
(1, 'Fashion'),
(2, 'Kids');
-- --------------------------------------------------------
-- Table structure for table `shop`
CREATE TABLE `shop` (
`store_id` int(10) NOT NULL auto_increment,
`shop_name` varchar(255) NOT NULL,
`cat_id` int(10) NOT NULL,
`subcat_id` int(10) NOT NULL,
PRIMARY KEY (`store_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `shop` (`store_id`, `shop_name`, `cat_id`, `subcat_id`) VALUES
(1, 'Test Store', 1, 1),
(2, 'Test Store 1', 1, 1),
(3, 'Another Store', 1, 3);
-- --------------------------------------------------------
-- Table structure for table `subcategory`
CREATE TABLE `subcategory` (
`subcat_id` int(10) NOT NULL auto_increment,
`cat_id` int(10) NOT NULL,
`heading` varchar(255) NOT NULL,
PRIMARY KEY (`subcat_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `subcategory` (`subcat_id`, `cat_id`, `heading`) VALUES
(1, 1, 'Women'),
(2, 1, 'General'),
(3, 1, 'Men'),
(4, 2, 'Children');
if i use the below query i get the following output
SELECT
`category`.`heading` AS `category`
, `subcategory`.`heading` AS `subcategory`
, COUNT(`shop`.`subcat_id`) AS cnt
FROM
`test`.`shop`
INNER JOIN `test`.`subcategory`
ON (`shop`.`subcat_id` = `subcategory`.`subcat_id`)
INNER JOIN `test`.`category`
ON (`shop`.`cat_id` = `category`.`cat_id`)
GROUP BY `shop`.`subcat_id`
HAVING (COUNT(`shop`.`subcat_id`) !='');
categorysubcategorycnt
FashionWomen2
FashionMen1
but i want to group concat the subcategory like below
categorysubcategory
FashionWomen,2|Men,1
Try this
SELECT t.category,
GROUP_CONCAT(CONCAT(t.subcategory,',',t.cnt) SEPARATOR '|') `concat`
FROM (
SELECT
`category`.`heading` AS `category`
, `subcategory`.`heading` AS `subcategory`
, COUNT(`shop`.`subcat_id`) AS cnt
FROM
`shop`
INNER JOIN `subcategory`
ON (`shop`.`subcat_id` = `subcategory`.`subcat_id`)
INNER JOIN `category`
ON (`shop`.`cat_id` = `category`.`cat_id`)
GROUP BY `shop`.`subcat_id`
) t
GROUP BY t.category
Note group concat has a default limit of 1024 character but it can be increased by following the manual
Fiddle Demo
Not a recommended output format, but easily done with a nested subquery:
SELECT category,
group_concat(subcategory, ',', cnt separator '|') as vals
FROM (SELECT c.`heading` AS `category`, sc.`heading` AS `subcategory`,
COUNT(`shop`.`subcat_id`) AS cnt
FROM `test`.`shop` s INNER JOIN
`test`.`subcategory` sc
ON s.`subcat_id` = sc.`subcat_id`) INNER JOIN
`test`.`category` c
ON s.`cat_id` = c.`cat_id`
GROUP BY c.`heading`, sc.`heading`
) sc
GROUP BY category;
Your having clause is unnecessary. It is just checking that there is at least one row for each group. But there is one, because you are using inner join.

Executing multiple join with expressions on Zend Framework 2

Actually I'm working on a project and I'm looking on how Zend Framework 2 handle complex queries (expecially on how to join n:m tables and how to use GROUP_CONCAT and other functions). Do you know the best practice to execute this query:
SELECT o. * , x.group_one, x.group_two
FROM table_one AS o
LEFT JOIN (
SELECT r.fk1, GROUP_CONCAT( t.field_one ) AS group_one, GROUP_CONCAT( t.field_two ) AS group_two
FROM table_three AS r
INNER JOIN table_two AS t ON r.fk2 = t.id
GROUP BY r.fk1
) AS x ON o.id = x.fk1
LIMIT 0 , 20;
using this db schema:
--
-- Database: `table-test-1`
--
-- --------------------------------------------------------
--
-- Structure of table `table_one`
--
CREATE TABLE `table_one` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`field_1` varchar(255) NOT NULL,
`field_2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
--
-- Dump for table `table_one`
--
INSERT INTO `table_one` (`id`, `field_1`, `field_2`) VALUES
(1, 'baz', 'bat'),
(2, 'foo', 'bar'),
(3, 'foo2', 'bat2'),
(4, 'fuz', 'bar2'),
(5, 'poo', 'pee');
-- --------------------------------------------------------
--
-- Structure of table `table_three`
--
CREATE TABLE `table_three` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`fk1` bigint(20) NOT NULL,
`fk2` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1` (`fk1`,`fk2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
--
-- Dump for table `table_three`
--
INSERT INTO `table_three` (`id`, `fk1`, `fk2`) VALUES
(5, 1, 1),
(1, 1, 2),
(6, 1, 4),
(2, 2, 2),
(4, 3, 2),
(7, 3, 3),
(3, 4, 1),
(8, 5, 3),
(9, 5, 4);
-- --------------------------------------------------------
--
-- Structure of table `table_two`
--
CREATE TABLE `table_two` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`field_one` varchar(255) NOT NULL,
`field_two` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Dump for table `table_two`
--
INSERT INTO `table_two` (`id`, `field_one`, `field_two`) VALUES
(1, 'label_name_1', 'label_extended_name_1'),
(2, 'label_name_2', 'label_extended_name2'),
(3, 'label_name_3', 'label_extended_name_3'),
(4, 'label_name_4', 'label_extended_name4');
At the moment I solved using a Zend\Db\Sql\Sql statement with an handmade query, but I'd like to know if there is, actually, a way to do this with a native Select() (possibly without using Doctrine or similar).
Thank you in advance :)
You have to import use Zend\Db\Sql\Predicate\Expression; to use group_concat.
Ex:
$sql = new Sql($this->adapter);
$select = $sql->select();
$select->columns(array('*'));
$select->from('tblCGii');
$select->join("tblCGFieldValues", "tblCGii.id = tblCGFieldValues.Cgii_id", array("field_values"=>new Expression("Group_Concat(tblCGFieldValues.field_values)")),"LEFT");
$select->group('tblCGii.id');

Count function()

I have these two table with some data sample in them. I would like to to pull out number of classifieds in each category. I gave it a try, and I got (2) in each one which is not correct. So hopefully someone will help me with this.
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`name` text COLLATE utf8_unicode_ci NOT NULL,
`subcategory_id` int(2) NOT NULL DEFAULT '0',
`parent_id` int(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=27 ;
--
-- Dumping data for table `categories`
--
INSERT INTO `categories` (`id`, `name`, `subcategory_id`, `parent_id`) VALUES
(1, 'Announcements', 0, 0),
(2, 'Employment', 0, 0),
(3, 'Items For Sale', 0, 0),
(4, 'Services', 0, 0),
(5, 'Garage Sales', 0, 0),
(6, 'Automobiles', 0, 0),
(7, 'Announcement1', 1, 1),
(8, 'Announcement2', 1, 1),
--
-- Table structure for table `classifieds`
--
CREATE TABLE IF NOT EXISTS `classifieds` (
`classified_id` int(255) NOT NULL AUTO_INCREMENT,
`title` text COLLATE utf8_unicode_ci NOT NULL,
`description` text COLLATE utf8_unicode_ci NOT NULL,
`category_id` int(10) NOT NULL,
`name` text COLLATE utf8_unicode_ci NOT NULL,
`authorized` int(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`adid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=177 ;
--
-- Dumping data for table `classifieds`
--
INSERT INTO `classifieds` (`classified_id`, `title`, `description`, `category_id`, `name`, `authorized`) VALUES
(1, 'Test Classified', 'Here is the First Test classified listing.', 1, 1);
INSERT INTO `classifieds` (`classified_id`, `title`, `description`, `category_id`, `name`, `authorized`) VALUES
(2, 'GMC For Sell', 'Looks like new 1979 GMC.', 6, 1);
here
$query = "SELECT category_id, COUNT(title) FROM classifieds GROUP BY category_id";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result)
$num_items_in_category = $row['COUNT(title)'];
echo "<><a href='category-".$row['id'].".php' >".$row['name'].$num_items_in_category."</a></li>";
Thanks
Change the SQL a bit, and loop through the results?
$query = "SELECT c.id, c.name,
COUNT(cl.category_id) AS num_items_in_category
FROM category_id c
LEFT JOIN aclassifieds cl ON cl.category_id=c.id
GROUP BY c.id";
$result = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
echo "<li><a href='category-".$row['id'].".php' >".$row['name'].$row['num_items_in_category']."</."</a></li>";
}
Just in case someone else wants to benefit my this:
enter $query = "SELECT c.id, c.name,
COUNT(cl.title) AS num_items_in_category
FROM categories c
LEFT JOIN classifieds cl ON cl.category_id=c.id
GROUP BY c.id";
$result = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
echo "".$row['name'].$row['num_items_in_category']."";
}
here
Thanks

Categories