Count on work history log - mysql

I have a table request:
and a table requesthx:
A single Request can have many log updates by multiple techs. For example, tech1 can create a log for the initial phone contact and add notes in the log section. Then tech2 could take those notes and complete a portion of the job requirement. Tech 3 could also be working on the same job waiting for a scheduled appointment.
If tech3 is logged in, I'd like to display a count of every open ticket for tech3.
What is the best way to accomplish this?
I've completed several ugly queries that had queries running within foreach loops to add to a count variable, but this seems like the really long way to reach a simple count total.
I've tried...
SELECT requesthx.hxID, requesthx.requestID,
requesthx.datetime_gmt, requesthx.log, requesthx.techID, requesthx.status,
COUNT($requestTable.requestID) AS tickets, request.status, requesthx.techID
FROM requesthx
LEFT JOIN request
ON (requesthx.requestID = request.requestID)
WHERE (requesthx.status <> 'closed'
AND request.status = 'open'
AND requesthx.techID = '1')
GROUP BY requesthx.techID;
...on a query that had 5 open tickets with techID = 1. I only receive 1 as the count. Any ideas?

You are correct the database has a way of counting this kind of information.
Select count(*) as "TicketCount"
From requesthx
Where techid=3
And status = "open"
Group by techid

I assume my own value for status fields in both tables
SELECT
`requesthx`.`hxID`
, `requesthx`.`requestID`
, `requesthx`.`datetime_gmt`
, `requesthx`.`log`
, `requesthx`.`techID`
, `requesthx`.`status`
, COUNT(`request`.`requestID`) AS tickets
, `request`.`status`
, `requesthx`.`techID`
FROM
`requesthx`
LEFT JOIN `test`.`request`
ON (`requesthx`.`requestID` = `request`.`requestID`)
WHERE (`requesthx`.`status` ="logged"
AND `request`.`status` ="open"
AND `requesthx`.`techID` =3)
GROUP BY `requesthx`.`techID`;

Related

MYSQL Query - Checking result is true/false and count

I am trying to check if the current user is already following the selected user, and I am doing this like so:
(I know it's not the best way, but as I am new to MYSQL this is as much as I have been able to come up with)
SELECT EXISTS (SELECT 1 FROM Activity WHERE IdOtherUser = 86 AND id = 145)
I am '145' and the user I selected is '86'.
Now that return '0' If I am not following and '1' If I am following that person.
Seems to be working already but it definetly needs improving!
Now what I would like to do is count the followers in the same query.
So count the people I am following and the people following me.
'Activity' is the table where I store the followers and I save them like this:
'id' = me
'idOtherUser' = other user I followed
'type' = type of action "follow"
I have done count's before when calculating the like counts, but I just cannot get my head around this!!
If anyone could spare some time to help me it is much appreciated!
I am sorry if the question is not the best, but I am still learning and trying my best to format them as clear as possible to understand.
Thanks in advance!!
If you trying to count the followers from specific id from table Activity you might do this way:
SELECT COUNT(idOtherUser) AS "I Follow",
(SELECT COUNT(idOtherUser) FROM Activity WHERE idOtherUser = 145 AND type = "follow"
) AS "FOLLOW ME",
(SELECT COALESCE(id,0) FROM Activity WHERE IdOtherUser = 86 AND id = 145 AND type = "follow")
FROM Activity WHERE id = 145 AND type = "follow"
you can use a "correlated subquery" to simplify the query and you might want distinct in the count also (depends on you data). I would avoid using spaces in column aliases too.
SELECT
COUNT(DISTINCT A1.idOtherUser) as i_follow
, (
SELECT
COUNT(DISTINCT A2.id)
FROM Activity A2
WHERE A2.idOtherUser = A1.id
AND A2.type = 'follow'
) as following_me
FROM Activity A1
WHERE A1.id = 145
AND A1.idOtherUser = 86
AND A1.type = 'follow'
Try it with distinct then without, if the result is the same leave distinct out of the query.

Rails 4 .where.not

pry(main)> Loan.joins(:statistics).where(state: <some states>).where.not(statistics: {state: <some other states>}).order(created_at: "desc").last.statistics.map(&:state)
2015-09-21 20:53:54,423|65310|DEBUG|development| - Loan Load (0.9ms) SELECT `loans`.* FROM `loans` INNER JOIN `statistics` ON `statistics`.`loan_id` = `loans`.`id` WHERE `loans`.`state` IN ('started', 'pending_declined') AND (`statistics`.`state` NOT IN ('prequalified', 'conditionally_approved', '4506t_results_uploaded', 'customer_forms_uploaded', 'ready_for_etran', 'etran_verified', 'forms_to_be_verified', 'forms_verified', 'credit_memo_entered', 'loandoc_generated', 'loandoc_completed', 'loandoc_customer_received_need_signatures', 'signatures_checked_and_uploaded', 'boarded')) ORDER BY `loans`.`created_at` ASC LIMIT 1
2015-09-21 20:53:54,426|65310|DEBUG|development| - Statistic Load (0.3ms) SELECT DISTINCT `statistics`.* FROM `statistics` WHERE `statistics`.`loan_id` = 97
=> ["started", "prequalified", "conditionally_approved", "customer_forms_uploaded", "ready_for_etran", "pending_declined"]
So, maybe I'm not understanding what's going on here... I'm asking SQL to find me some Loans where their Statistics do not contain certain values. In this example, I'm saying to leave out any loans with a Statistic of prequalified, but, as you can see from the print out, the Loan#statistics does have prequalified, along with several other states I'd like to leave out.
Can anyone shed some light on this? I've been fighting with it for hours, and my head is spinning at this point.
With that ActiveRecord query, you've:
First, found a set of loans
next, ordered by created_at
then, used last to find limit to 1 result, finding the oldest of the set
So, you have an instance of Loan.
Since you called #statistics on the method, I can infer that loan has_many :statistics, and you've found all statistics that holds a foreign key value that matches the instance of Loan that you found. Now you have set of statistics.
For the set of statistics, you've mapped them to the map attribute.
Since you've already joined the statistics try removing .last.statistics from your query. User map on the result set to its state. Also, consider using #includes or #select.
It because you use last.statistics. It means the result on loan object will be joined with statistics whereas you have created condition before.
Look at your last result query:
Statistic Load (0.3ms) SELECT DISTINCT `statistics`.* FROM `statistics` WHERE `statistics`.`loan_id` = 97
remove your last.statistics
Loan.joins(:statistics).where(state: <some states>).where.not(statistics: {state: <some other states>}).order(created_at: "desc").map(&:state)
or
if you want to add condition to determine some loans that you need in before map(&state)
Loan.joins(:statistics).where(state: <some states>).where.not(statistics: {state: <some other states>}).where("loans.id IN (97)").order(created_at: "desc")
You query returns product of Loan and Statistic so it still returns Loan records that have some Statistic that does not have state you specified.
If you only want Loan that has no Statistic on those states at all you probably want your SQL to be something along this line:
SELECT loans.*,
FROM loans
LEFT OUTER JOIN (
SELECT statistics.loan_id, COUNT(*) count
FROM quotes
WHERE statistics.state IN ('prequalified', 'conditionally_approved')
GROUP BY statistics.loan_id
) statistics
ON statistics.loan_id = loans.id
WHERE loans.state IN ('started', 'pending_declined')
AND statistics.count IS NULL;
My SQLfu is not what I'd be proud of so this might not be the most optimised query ever but it should get the result you expect.
You could convert that to ActiveRecord query interface but unfortunately subquery and LEFT JOIN are not really supported, at least not in the way that we going to use it will be something like this:
join_query = <<SQL
LEFT OUTER JOIN (
SELECT statistics.loan_id, COUNT(*) AS count
FROM statistics
WHERE statistics.state IN (<<state>>)
) statistics ON loans.id = statistics.loan_id
SQL
Loan
.joins(join_query)
.where(statistics: { count: null })
.where(state: <<somestate>>)
.order(created_at: :desc)
The <<SQL ... SQL is Heredoc by the way if you're not familiar with it.

Leave out certain dates on Access report

I have a report in Access 2013 that prints an equipment log. There is a bunch of dates listed for each piece of equipment. I wanted to only print the newest date for each piece of equipment. I have searched the internet and this site with no luck. So any suggestions will be greatly appreciated.
My SQL statement is:
SELECT dbo_eq_location_transfer_d.equipment_id, dbo_equipment.description, dbo_eq_location_transfer_d.transaction_no, dbo_eq_location_transfer_d.job_no, dbo_jobs.description, dbo_eq_location_transfer_d.date_booked, dbo_eq_location_transfer_d.delivery_time, dbo_eq_location_transfer_d.line_no, dbo_eq_location_transfer_d.row_modified_by, dbo_eq_location_transfer_d.comment
FROM (dbo_eq_location_transfer_d INNER JOIN dbo_jobs ON dbo_eq_location_transfer_d.job_no = dbo_jobs.job_no) INNER JOIN dbo_equipment ON dbo_eq_location_transfer_d.equipment_no = dbo_equipment.equipment_no
ORDER BY dbo_eq_location_transfer_d.equipment_id, dbo_eq_location_transfer_d.transaction_no;
The date_booked field is the date field I am trying narrow down. I have a simple SQL query that works and I have been trying copy that into the about SQL but cannot seem to get it to mesh. It is:
SELECT [dbo_eq_location_transfer_d.equipment_no], Max(dbo_eq_location_transfer_d.date_booked) AS ["Newest Date"]
FROM dbo_eq_location_transfer_d
GROUP BY [dbo_eq_location_transfer_d.equipment_no];
In your query set the date fields criteria to:
>Now()-30
This will show any dates for the last 30 days just change 30 to the number of days you want to see.
Now that I understand your structure & data, here is what I did:
(1) Create the following query to select only the most recent 'date_booked' for each 'equipment_no'; save the query with name '23020071_A':
SELECT dbo_eq_location_transfer_d.equipment_no,
First(dbo_eq_location_transfer_d.transaction_no) AS FirstOftransaction_no,
First(dbo_eq_location_transfer_d.job_no) AS FirstOfjob_no,
First(dbo_eq_location_transfer_d.date_booked) AS FirstOfdate_booked
FROM (dbo_eq_location_transfer_d
INNER JOIN dbo_jobs ON dbo_eq_location_transfer_d.job_no = dbo_jobs.job_no)
INNER JOIN dbo_equipment ON dbo_eq_location_transfer_d.equipment_no = dbo_equipment.equipment_no
GROUP BY dbo_eq_location_transfer_d.equipment_no
ORDER BY First(dbo_eq_location_transfer_d.date_booked) DESC;
(2) I created the following query combining the new query with your existing query:
SELECT dbo_eq_location_transfer_d.equipment_id, dbo_equipment.description,
dbo_eq_location_transfer_d.transaction_no, dbo_eq_location_transfer_d.job_no,
dbo_jobs.description, dbo_eq_location_transfer_d.date_booked,
dbo_eq_location_transfer_d.delivery_time, dbo_eq_location_transfer_d.line_no,
dbo_eq_location_transfer_d.row_modified_by, dbo_eq_location_transfer_d.comment
FROM 23020071_A INNER JOIN ((dbo_eq_location_transfer_d
INNER JOIN dbo_jobs ON dbo_eq_location_transfer_d.job_no = dbo_jobs.job_no)
INNER JOIN dbo_equipment ON dbo_eq_location_transfer_d.equipment_no = dbo_equipment.equipment_no)
ON ([23020071_A].FirstOftransaction_no = dbo_eq_location_transfer_d.transaction_no)
AND ([23020071_A].equipment_no = dbo_eq_location_transfer_d.equipment_no)
AND ([23020071_A].FirstOfjob_no = dbo_eq_location_transfer_d.job_no)
ORDER BY dbo_eq_location_transfer_d.equipment_id, dbo_eq_location_transfer_d.transaction_no;
Now when I run the second query, it returns only the most recent row for that piece of equipment.

How to make a 1 column query by choosing from two columns mysql

I have a messaging system (very basic) that has a table like this:
**MESSAGE_ID** **RUSER_ID** **SUSER_ID** **MESSAGE_DATA** **DATE**
RUSER is the receiving user, and SUSER is the sending user. If I wanted to output a query that would output a certain users messages, I would currently do:
Select * from PRIVATE_MESG where RUSER_ID=$USER_ID or SUSER_ID=$USER_ID
That would give me all message_id's that are associated with that USER_ID. What I would like, is to create a column that would produce only the ID associated with RUSER_ID or SUSER_ID associated with a specific user. I need it to choose the messages that RUSER_ID or SUSER_ID are equal to a USER_ID but only display the one that isn't USER_ID
I would then like to do a group by the output of that query.
Any help is greatly appreciated!
Thanks!
update I am not really looking for a message_id, I am just looking for a list of users who that person has written to or received from.
UPDATE
Just so everyone knows, I recieved the answer to this question perfectly! I tweaked it later on so that it would also display them by date from newest to oldest. I did this by spliting the DATETIME into DATE and TIME USING the DATE() and TIME() Function. Here was my final query:
SELECT
IF(RUSER_ID = $USER, SUSER_ID, RUSER_ID) as THE_OTHER_GUY, DATE(DATE) as DAY, TIME(DATE) as TIME
FROM PRIVATE_MESG
WHERE RUSER_ID = $USER
OR SUSER_ID = $USER;
group by THE_OTHER_GUY ORDER BY DAY DESC, TIME DESC
Hope this helps the next person!
You can query:
SELECT
*,
IF(RUSER_ID = $USER_ID, SUSER_ID, RUSER_ID) as THE_OTHER_GUY
FROM PRIVATE_MESG
WHERE RUSER_ID = $USER_ID
OR SUSER_ID = $USER_ID;
SELECT SUSER_ID FROM PRIVATE_MESG WHERE RUSER_ID=$USER_ID
UNION
SELECT RUSER_ID FROM PRIVATE_MESG WHERE SUSER_ID=$USER_ID
It retrieves:
- the list of user IDs who sent messages to $USER_ID
- the list of user IDs who received messages from $USER_ID
And UNION groups the 2 lists in a single result set.

SQL Query returns fake duplicate results?

I've been trying to write a few little plugins for personal use with WHMCS. Essentially what I'm trying to do here is grab a bunch of information about a certain order(s), and return it as an array in Perl.
The Perl bit I'm fine with, it's the MySQL query I've formed that's giving me stress..
I know it's big and messy, but what I have is:
SELECT tblhosting.id, tblhosting.userid, tblhosting.orderid, tblhosting.packageid, tblhosting.server, tblhosting.domain, tblhosting.username, tblorders.invoiceid, tblproducts.gid, tblservers.ipaddress, tblinvoices.status
FROM tblhosting, tblproducts, tblorders, tblinvoices, tblservers
WHERE tblorders.status = 'Pending'
AND tblproducts.gid = '2'
AND tblservers.id = tblhosting.server
AND tblorders.id = tblhosting.orderid
AND tblinvoices.id = tblorders.invoiceid
AND tblinvoices.status = 'Paid'
I don't know if this /should/ work, but I assume I'm on the right track as it does return what I'm looking for, however it returns everything twice.
For example, I created a new account with the domain 'sunshineee.info', and then in PHPMyAdmin ran the above query.
id userid orderid packageid server domain username invoiceid gid ipaddress status
13 7 17 6 1 sunshineee.info sunshine 293 2 184.22.145.196 Paid
13 7 17 6 1 sunshineee.info sunshine 293 2 184.22.145.196 Paid
Could anyone give me a heads up on where I've gone wrong with this one.. Obvioiusly (maybe not obviously enough) I want this as only one row returned per match.. I've tried it with >1 domain in the database and it returned duplicates for each of the matches..
Any help would be much appreciated
:)
SELECT distinct tblhosting.id, tblhosting.userid, tblhosting.orderid, tblhosting.packageid, tblhosting.server, tblhosting.domain, tblhosting.username, tblorders.invoiceid, tblproducts.gid, tblservers.ipaddress, tblinvoices.status
FROM tblhosting, tblproducts, tblorders, tblinvoices, tblservers
WHERE tblorders.status = 'Pending'
AND tblproducts.gid = '2'
AND tblservers.id = tblhosting.server
AND tblorders.id = tblhosting.orderid
AND tblinvoices.id = tblorders.invoiceid
AND tblinvoices.status = 'Paid'
Well, its near impossible without any table definitions, but you are doing a lot of joins there. You are starting with tblhosting.id and working your way 'up' from there. If any of the connected tables has a double entry, you'll get more hits
You could add a DISTINCT to your query, but that would not fix the underlying issue. It could be a problem with your data: do you have 2 invoices? Maybe you should select everything (SELECT * FROM) and check what is returned, maybe check your tables for double content.
Using DISTINCT is most of the time not a good choice: it means either your query or your data is incorrect (or you don't understand them thoroughly). It might get you the right result for now, but can get you in trouble later.
A guess about the reason this happens:
You do not connect the products table to the chain of id's. So you are basically adding a '2' to your result as far as I can see. You join on products, and the only thing that limits that table is that "gid" should be 2. So if you add a product with gid 2 you get another result. Either join it (maybe tblproduct.orderid = tblorders.id ? just guessing here) or just remove it, as it does nothing as far as I can see.
If you want to make your query a bit clearer, try not implicitly joining, but do it like this. So you can actually see what's happening
SELECT tblhosting.id, tblhosting.userid, tblhosting.orderid, tblhosting.packageid, tblhosting.server, tblhosting.domain, tblhosting.username, tblorders.invoiceid, tblproducts.gid, tblservers.ipaddress, tblinvoices.status
FROM tblhosting
JOIN tblproducts ON /*you're missing something here!*/
JOIN tblorders ON tblorders.id = tblhosting.orderid
JOIN tblinvoices ON tblinvoices.id = tblorders.invoiceid
JOIN tblservers ON tblservers.id = tblhosting.server
WHERE
tblorders.status = 'Pending'
AND tblproducts.gid = '2'
AND tblinvoices.status = 'Paid'
I don't see in your query JOIN to tblproducts, it seems to be a reason.