I need help creating a specific query, The following is an example of my deposit table, empId is a foreign key that refers to the primary key of my 'users' table which is 'userId'
Note:users table is not shown here
mysql> SELECT * FROM deposit
-> ;
+------------+---------------+---------+-------------+-------------+-------------+-------+
| CheckId | jobId | payRate | jobLocation | hours | date_paid | empId |
+------------+---------------+---------+-------------+-------------+-------------+-------+
| 1512 | entertainment | 12 | store1 | 10.00 | 2013-03-02 | 1 |
| 1510 | entertainment | 12 | store1 | 8.00 | 2013-03-01 | 1 |
| 1507 | retail | 10 | store1 | 8.00 | 2013-03-18 | 1 |
| 1506 | retail | 10 | store1 | 20.00 | 2013-03-19 | 1 |
+------------+---------------+---------+-------------+-------------+-------------+-------+
What i want is to calculate the sum of all hours for all specific jobId , in this case if i did the
query correctly it would look like this:
+---------------+---------------+---------+
| payID | payRate | hours |
+---------------+---------------+---------+
| entertainment| 12 | 18 |
| retail | 10 | 28 |
+---------------+---------------+---------+
In this case there is only two jobIds but it could have more than 2
This is the query i have and its only showing one payId, so I need help fixing it
also note that email is an attribute of my users table
<table>";
$query = "SELECT jobId, payRate, SUM(hours) AS 'All_Hours'
FROM users INNER JOIN deposit ON userId = empId
WHERE users.email = '" . $_SESSION['email'] ."'
GROUP BY jobId,payRate";
if (!$result) { //if the query failed
echo("Error, the query could not be executed: " .
mysqli_error($db) . "</p>");
mysqli_close($db); //close the database
} //by now we have made a successful query
while ($row = mysqli_fetch_assoc($result)){
echo "<tr><td>" .$row['jobId'] . "</td>
<td>" .$row['payRate'] . "</td>
<td>" .$row['All_Hours'] . "</td>
</tr>";
}
echo"</table>
you forgot to add GROUP BY clause in your query causing to have only one record in the result,
SELECT jobId, payRate, SUM(hoursWorked) AS 'All_Hours'
FROM users INNER JOIN paycheck ON userId = empId
WHERE users.email = 'session_email_here'
GROUP BY jobId, payRate
On the deposit table
SELECT jobId, payRate, sum(hours) FROM deposit
group by 1, 2
I would also suggest that you make it little bit more relational: jobId and jobLocation needs to be moved to new tables
Related
Am trying to group user orders by the order id, but am not getting it right i know this will be first get done in the SQL query then organise it well in PHP and HTML but i don't know how to get it done.
orderinfo
oid | userid | total | payid
-----|---------|--------|----------
oi10 | peter | 650 | VCC-100
oi12 | john | 30 | VCC-500
oi15 | peter | 60 | COD-500
itemorder
pid | ioid | userid | price | qty | itemname
----| ------|---------|--------|-----|-----------
p10 | oi10 | peter | 200 | 1 | lexus
p20 | oi10 | peter | 150 | 1 | Toyota
p15 | oi10 | peter | 300 | 1 | Myvi
p66 | oi15 | peter | 25 | 2 | BMW
p67 | oi15 | peter | 10 | 1 | Saga
p67 | oi12 | john | 10 | 3 | Saga
My current Code
$handler->prepare('
SELECT * FROM itemorder io
LEFT JOIN orderinfo oi
ON io.oid = oi.ioid
WHERE io.userid = 'peter'
GROUP BY io.oid
ORDER BY oi.pid DESC
');
$handler->execute();
$RecentOrder = $handler->getAll();
$handler->free();
if(!empty($RecentOrder)){
foreach($RecentOrder as $row){
}
}
Expected Result
I want the result to be sorted according to the order id all item that has same order id will be listed (list according to order id).
oid: oi10
--------
lexus
Toyota
Myvi
---------------------
oid: oi15
--------
BMW
Saga
The desired output can be retrieved with just ORDER BY.
SELECT *
...
ORDER BY oi.oid DESC, io.pid DESC
And then do the specific formatting in PHP. Easiest way is probably to remember the order_id of the last row.
$lastOrderId = null;
foreach ($result as $row) {
if ($lastOrderId != $row['oid']) {
echo 'oid: ' . $row['oid'] . PHP_EOL;
echo ' -----------' . PHP_EOL;
}
echo ' ' . $row['itemname'] . PHP_EOL;
$lastOrderId = $row['oid'];
}
You can try this :
SELECT io.ioid,GROUP_CONCAT("",io.itemname) as order_items FROM itemorder as io
LEFT JOIN orderinfo as oi
ON io.ioid = oi.oid
WHERE io.userid = 'peter'
GROUP BY io.ioid
ORDER BY io.pid DESC
Please not the columns on which join is done.
Then in PHP you can use explode function to get the array of names for each order.
Hope this helps!
Given the following Database setup:
Customers
| customerId | accountId | addressId |
|------------|-----------|-----------|
| 1 | 110 | 8 |
| 2 | 120 | 9 |
| 3 | 130 | 10 |
Address
| addressId | companyName | state |
|-----------|-------------|-------|
| 8 | FooBar Co | FL |
| 9 | Self Co | VA |
| 10 | Cli Co | CA |
Tests
| testId | accountId | testType | Status |
|--------|-----------|----------|---------|
| 1 | 120 | Urine | Done |
| 2 | 110 | Blood | Pending |
| 3 | 110 | Blood | Pending |
| 4 | 130 | Biopsy | Done |
| 5 | 130 | Blood | Done |
| 6 | 130 | Urine | Pending |
| 7 | 110 | Biopsy | Pending |
| 8 | 120 | Urine | Pending |
| 9 | 110 | Biopsy | Pending |
| 10 | 110 | Urine | Pending |
Is there a way for me to get around having to loop through a mysqli result set of customers in order to grab the COUNT of each testType based on the name of the type of test and based on the accountId. So for example I am currently doing this:
$sql = "SELECT C.accountId, A.companyName
FROM Customers C
JOIN Address A
ON C.addressId=A.addressId";
$result = mysqli_query($connection, $sql);
$customers = mysqli_fetch_all($result, MYSQLI_ASSOC);
foreach( $customers as $customer ) :
echo '<h2>' . $customer["companyName"] . '</h2>';
// Urine Tests Count
$sql = 'SELECT COUNT(testId) as count FROM Tests WHERE accountId=' . $customer["accountId"] . ' AND testType="Urine"';
$result = mysqli_query($connection, $sql);
$testCount = mysqli_fetch_array($result, MYSQLI_ASSOC);
echo '<p>Total Urine Tests: ' . $testCount["count"] . '</p>';
// Biopsy Tests Count
$sql = 'SELECT COUNT(testId) as count FROM Tests WHERE accountId=' . $customer["accountId"] . ' AND testType="Biopsy"';
$result = mysqli_query($connection, $sql);
$testCount = mysqli_fetch_array($result, MYSQLI_ASSOC);
echo '<p>Total Biopsy Tests: ' . $testCount["count"] . '</p>';
// Blood Tests Count
$sql = 'SELECT COUNT(testId) as count FROM Tests WHERE accountId=' . $customer["accountId"] . ' AND testType="Blood"';
$result = mysqli_query($connection, $sql);
$testCount = mysqli_fetch_array($result, MYSQLI_ASSOC);
echo '<p>Total Blood Tests: ' . $testCount["count"] . '</p>';
endforeach;
As you can probably tell this is hella repetative but so far it's been the only way to get the information I want. I know I could do a COUNT() with a GROUP BY for the tests once I am inside the foreach loop, but if I do that, I won't get back 0 for tests that customer might not have and I need to display if a testType has 0.
I am a lot more well versed in PhP then I am in MySQLi and SQL. Is there something I am missing here? Surely there has to be a better way to get all of this, maybe even get it in one query? Any suggestions or a point in the right direction would be great.
Simple aggregation and a left join or two on your main query should do it. A cross join could be used to identify the unique test types and by cross joining this to a customer/address 1:1 relationship we generate a row for each test type for every customer. That way each customer will have one of each type listed with the appropriate count (0) when no tests of that type exist for an account.
SELECT C.accountId, A.companyName, Z.TestType, Count(distinct T.TestID)
FROM Customers C
LEFT JOIN Address A
ON C.addressId=A.addressId
CROSS JOIN (Select Distinct TestType from Tests) Z
LEFT JOIN Tests T
on T.AccountID = C.AccountID
and Z.TestType = T.TestType
and ReceiveDT>=SomeDate
and ReceiveDT<=SomeOtherDate
GROUP BY C.accountId, A.companyName, Z.TestType
LEFT Joinn will return all customer records and only those with address that match and only records from test matching a customer record. So count will be 0 when no type/test match.
Customer:Address:TestTypes:Tests cardinality expected: 1:1:M:M
so if there were only 3 types of tests I would expect to see 3* the number of records in customers in the results. This is because Address and customers appear to be a 1:1 the number of test types will determine how many times we replicate a customer record and the left join to tests is being aggregated so it will not add to the row count.
Obviously you can add a where clause if you need to limit to a specific customer, but I thought you wanted all customers's test type counts for all possible test types.
I have this table (sample)
|---id---|---place---|---admin---|
| 1 | Q | AJ |
| 2 | p | PM |
| 3 | w | AJ |
| 4 | t | TY |
| 5 | u | AJ |
I want to count how many places each admin control using MYSQLi not mysql.
I have searched and all what I found is MYSQL and using COUNT(*) and when I am trying to use it, does not work.
Thanks all in advance.
$result = mysqli_query("SELECT admin, COUNT(admin) as 'amount' FROM tablename GROUP BY admin");
while($row = mysqli_fetch_assoc($result))
echo "Name: " . $row['admin'] . " - ". $row['amount'] . "<br />";
Using count + GROUP by you can get the amount of times each admin appears in the table.
This is the bookings table I'm using for my query
+----------------------+
| event_id | person_id |
+----------------------+
| 5 | 7 |
| 4 | 7 |
| 3 | 7 |
| 4 | 5 |
| 3 | 5 |
| 5 | 3 |
+----------------------+
This table shows that person_id 7 has 3 bookings, 5 has 2 bookings and 3 has 6 bookings.
Currently, I'm using this query to get the total number of bookings per person.
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
bookings.event_id,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
$result = mysql_query($query);
if($result) {
while($row = mysql_fetch_array($result))
{
/* total bookings per user */
$value = $row['total'];
$sum += $value;
/* events booked per user */
$events....
/* Displaying results */
echo "<tr width='500'>";
echo "<td>".$row['person_id']."</td>";
echo "<td>".$row['display_name']."</td>";
echo "<td>".$row['total']."</td>";
echo "<td>".$events."</td>";
echo "</tr>";
}
This works okay and gives me:
+-----------------------------------+
| ID | NAME | Total Bookings |
+-----------------------------------+
| 7 | Bob | 3 |
| 5 | Jane | 2 |
| 3 | Joe | 1 |
+-----------------------------------+
I'm seeking help to get this to display the events booked by each person (like the 4th columns below):
+------------------------------------------------+
| ID | NAME | Total Bookings | Event IDs |
+------------------------------------------------+
| 7 | Bob | 3 | 5,4,3 |
| 5 | Jane | 2 | 4,3 |
| 3 | Joe | 1 | 5 |
+------------------------------------------------+
Could you please help me getting there.
Thanks.
GROUP_CONCAT https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
GROUP_CONCAT(bookings.event_id) as event_ids,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
A bit different query but same result:
SELECT
bookings.person_id,
COUNT(
bookings.person_id
) AS total,
users.display_name,
GROUP_CONCAT(
bookings.event_id
ORDER BY
bookings.event_id
) AS events_list
FROM
bookings,
users
WHERE
bookings.person_id=users.id
GROUP BY
bookings.person_id
ORDER BY
bookings.person_id
I don't know if for a large data, the execution time is less, more or equal.
I'm new to MySQL and PHP. I have two tables, one to hold all the company names and the other table has only the company name below the user:
Table 1
| # | Company name |
--------------------
| 1 | Microsoft |
| 2 | HP |
| 3 | Asus |
| 4 | Apple |
| 5 | Amazon |
| 6 | CCN |
table 2
| # | Company name | User name |
--------------------------------
| 1 | Asus | x1 |
| 2 | Apple | x1 |
| 3 | HP | x2 |
| 4 | Asus | x2 |
| 5 | Apple | x2 |
I need to create a query that achieves the following. First of all the companies are shown which are associated with a specific user (say Asus and Apple for user x1). After that, the remaining companies from table 1 are shown.
For example, the result of the query I'm looking for, for user X1 will display the rows in this way:
| # | Company name |
--------------------
| 1 | Asus |
| 2 | Apple |
| 3 | Microsoft |
| 4 | HP |
| 5 | Amazon |
| 6 | CCN |
How can I achieve this?
It looks like you want to include all companies, but for a given user, list the companies associated with that user first. If that's the case, you do not want to use an INNER JOIN.
Here's some SQL that should work. I've provided reasonable table and field names since you didn't give those. I'm also assuming that you have a reasonably sane table design with no duplicate rows.
SELECT c.company_name,
CASE
WHEN u.company_name IS NULL THEN 'N'
ELSE 'Y'
END AS user_has_company
FROM companies c
LEFT JOIN (
SELECT *
FROM users
WHERE user_name = 'x1'
) u
ON u.company_name = c.company_name
ORDER BY user_has_company DESC, c.company_name
This query will return an extra column - user_has_company. I'd use that to indicate whether the current user is associated with a given company, but you can ignore it if you want.
You will need a JOIN Statement to join another in the SELECT-Statement of table1
Quick example:
SELECT * FROM table2 INNER JOIN table1.id = table2.id WHERE table2.username = 'x1'
You'll find everything you need in the Documentation of JOINs.
http://dev.mysql.com/doc/refman/5.1/en/left-join-optimization.html
If you're just after the MySQL query for this then something like this would work
SELECT company_name,SUM(IF(user_name='x1',1,0)) as ordering
FROM `table2`
GROUP BY company_name
ORDER BY ordering DESC
But you should look at your schema before you go much further. If you have a column (company_name) in one table that refers to another table you should make that column refer to the PRIMARY KEY of the other table, i.e.
Table1
| # | company_name |
--------------------
| 1 | microsoft |
| 2 | hp |
| 3 | asus |
| 4 | apple |
| 5 | amazon |
| 6 | CCN |
table2
| # | company_id | user_name |
--------------------------------
| 1 | 3 | x1 |
| 2 | 4 | x1 |
| 3 | 2 | x2 |
| 4 | 3 | x2 |
| 5 | 4 | x2 |
This is one of the first things you learn in database design/normalisation. You will need to change your query in this case. Something like this:
SELECT company_name,SUM(IF(user_name='x1',1,0)) as ordering
FROM `table1`
LEFT JOIN `table2` ON table2.company_id=table1.id
GROUP BY company_name
ORDER BY ordering DESC
Create your query like this:
$sql = "SELECT b.companyName FROM table1 a INNER JOIN table2 b ON a.companyName = b.companyName WHERE b.userName = 'x1'";
Then, using PHP, use:
$con = mysql_connect("localhost","peter","abc123");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("my_db", $con);
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
echo $row['companyName'];
echo "<br />";
}
mysql_close($con);
Try this query:
SELECT company_name FROM table2 ORDER BY user_name ASC
In the HTML table, using PHP code:
$result = mysql_query(" SELECT company_name, user_name FROM table2 ORDER BY user_name ASC");
echo "<table>
<tr><th>Company Name</th><th>username</th></tr>";
while($row = mysql_fetch_array($result) {
echo "<tr><td>{$row['company_name']}</td><td>{$row['user_name']}</td></tr>";
}
echo "</table>"