How to create a Trac report containing all tickets needing an answer? - trac

We are using Trac to handle support for our clients.
I wonder if there is a way to create a report to help us identify the tickets unanswered. That is the ones where the last comment is not from the owner.
Any idea how to do that ?

It won't be too difficult with a little SQL knowledge. Take a look at Trac's Database Schema:
You get the owner field from the ticket table and join with the ticket-change table by ticket.id and ticket-change.ticket to get the comment information.
I'm not sure this is the best approach however. You should just set all answered tickets to closed and then use the report for showing any open tickets. Or modified the workflow to better suit the process by adding a unanswered stage.

Thanks for giving me the direction. I have started from an existing report and have managed to do what I want, changing it to this SQL query :
SELECT DISTINCT p.value AS __color__, id AS ticket,
summary, component, milestone, t.type AS type, status, resolution,
t.time AS created, changetime AS modified, reporter AS _reporter
FROM ticket t
LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority'
LEFT JOIN ticket_change tc ON id = tc.ticket
WHERE owner = $USER AND status <> 'closed' AND t.type = 'support' AND
(owner != (SELECT author FROM ticket_change WHERE time =
(SELECT MAX(tc.time) FROM ticket_change tc WHERE tc.ticket = id)))
ORDER BY CAST(p.value AS integer), tc.time, milestone, t.type
If that can help someone...

Related

Where can I find usage statistics in Redshift?

Before all thank you for your help!
I want to find out which tables in the database are most heavily used, i.e. the amount of users that query the table, the amount of times it was queried, the resources that where consumed by users per table, the total time the tables where queried, and any other useful data.
For now I would limit the analysis to 9 specific tables.
I'd tried using stl_scan and pg_user using the next two querys:
SELECT
s.perm_table_name AS table_name,
count(*) AS qty_query,
count(DISTINCT s.userid) AS qty_users
FROM stl_scan s
JOIN pg_user b
ON s.userid = b.usesysid
JOIN temp_mone_tables tmt
ON tmt.table_id = s.tbl AND tmt.table = s.perm_table_name
WHERE s.userid > 1
GROUP BY 1
ORDER BY 1;
SELECT
b.usename AS user_name,
count(*) AS qty_scans,
count(DISTINCT s.tbl) AS qty_tables,
count(DISTINCT trunc(starttime)) AS qty_days
FROM stl_scan s
JOIN pg_user b
ON s.userid = b.usesysid
JOIN temp_mone_tables tmt
ON tmt.table_id = s.tbl AND tmt.table = s.perm_table_name
WHERE s.userid > 1
GROUP BY 1
ORDER BY 1;
The temp_mone_tables is a temporal table that contains the id and name of the tables I'm interested.
With this queries I'm able to get some information but I need more details. Surprisingly there's not much data online about this kind of statistics.
Again thank you all beforehand!
Nice work! You are on the right track using the stl_scan table. I'm not clear what further details you're looking for.
For detailed metrics on resource usage you may want to use the SVL_QUERY_METRICS_SUMMARY view. Note that this data is summarized by query not table because a query is the primary way resources are utilized.
Generally, have a look at the admin queries (and views) in our Redshift Utils library on GitHub, particularly v_get_tbl_scan_frequency.sql
Thanks to Joe Harris' answer I was able to add a lot of information to my previous query. With svl_query_metrics_summary joined to stl_scan you get important data about resources consumption, this information can be extended joining them to the vast number of views listed in Joe's answer.
For me the solution begins with the next query:
SELECT *
FROM stl_scan ss
JOIN pg_user pu
ON ss.userid = pu.usesysid
JOIN svl_query_metrics_summary sqms
ON ss.query = sqms.query
JOIN temp_mone_tables tmt
ON tmt.table_id = ss.tbl AND tmt.table = ss.perm_table_name
The query gives you a lot of data that can be summarized in multiple ways as wanted.
Remember that temp_mone_tables is a temp table that contains the tableid and name of the tables I'm interested.

SQL Nearest Neighbor Query (Movie Recommendation Algorithm)

Need help making this (sort of) working query more dynamic.
I have three tables myShows, TVShows and Users
myShows
ID (PK)
User (FK to Users)
Show (FK to TVShows)
Would like to take this query and change it to a stored procedure that I can send a User ID into and have it do the rest...
SELECT showId, name, Count(1) AS no_users
FROM
myShows LEFT OUTER JOIN
tvshows ON myShows.Show = tvshows.ShowId
WHERE
[user] IN (
SELECT [user]
FROM
myShows
WHERE
show ='1' or show='4'
)
AND
show <> '1' and show <> '4'
GROUP BY
showId, name
ORDER BY
no_users DESC
This right now works. But as you can see the problem lies within the WHERE (show ='1' or show='4') and the AND (show <> '1' and show <> '4') statements which is currently hard-coded values, and that's what I need to be dynamic, being I have no idea if the user has 3 or 30 shows I need to check against.
Also how inefficient is this process? this will be used for a iPad application that might get a lot of users. I currently run a movie API (IMDbAPI.com) that gets about 130k hits an hour and had to do a lot of database/code optimization to make it run fast. Thanks again!
If you want the database schema for testing let me know.
This will meet your requirements
select name, count(distinct [user]) from myshows recommend
inner join tvshows on recommend.show = tvshows.showid
where [user] in
(
select other.[user] from
( select show from myshows where [User] = #user ) my,
( select show, [user] from myshows where [user] <> #user ) other
where my.show = other.show
)
and show not in ( select show from myshows where [User] = #user )
group by name
order by count(distinct [user]) desc
If your SQL platform supports WITH Common Table Expressions, the above can be optimized to use them.
Will it be efficient as the data sizes increase? No.
Will it be effective? No. If just one user shares a show with your selected user, and they watch a popular show, then that popular show will rise to the top of the ranking.
I'd recommend
a) reviewing your thinking of what recommends a show
b) periodically calculating the results rather than performing it on demand.

Need help with Join

So I'm trying to build a simple forum. It'll be a list of topics in descending order by the date of either the topic (if no replies) or latest reply. Here's the DB structure:
Topics
id, subject, date, poster
Posts
id, topic_id, message, date, poster
The forum itself will consist of an HTML table with the following headers:
Topic | Last Post | Replies
What would the query or queries look like to produce such a structure? I was thinking it would involve a cross join, but not sure... Thanks in advance.
Of course you can make a query for this, but I advise you to create in Topics table fields 'replies' and 'last post', then update them on every new post. That could really improve your database speed, not now, but the time when you will have thousands of topics.
SELECT *
FROM
`Topics`,
(
SELECT *, COUNT(*) AS `replies`
FROM `Posts`
GROUP BY `Posts`.`topic_id`
ORDER BY `Posts`.`date` DESC
) AS `TopicPosts`
WHERE `Topics`.`id` = `TopicPosts`.`topic_id`
ORDER BY `Posts`.`date` DESC
This 'should' work, or almost work in the case it doesn't, but I agree with the other poster, it's probably better to store this data in the topics table for all sorts of reasons, even if it is duplication of data.
The forum itself will consist of an
HTML table with the following headers:
Topic | Last Post | Replies
If "Last Post" is meant to be a date, it's simple.
SELECT
t.id,
t.subject,
MAX(p.date) AS last_post,
COUNT(p.id) AS count_replies
FROM
Topics t
INNER JOIN Posts p ON p.topic_id = t.id
GROUP BY
t.id,
t.subject
If you want other things to display along with the last post date, like its id or the poster, it gets a little more complex.
SELECT
t.id,
t.subject,
aggregated.reply_count,
aggregated.distinct_posters,
last_post.id,
last_post.date,
last_post.poster
FROM
Topics t
INNER JOIN (
SELECT topic_id,
MAX(p.date) AS last_date,
COUNT(p.id) AS reply_count,
COUNT(DISTINCT poster) AS distinct_posters
FROM Posts
GROUP BY topic_id
) AS aggregated ON aggregated.topic_id = t.id
INNER JOIN Posts AS last_post ON p.date = aggregated.last_date
As an example, I've added the count of distinct posters for a topic to show you where this approach can be extended.
The query relies on the assumption that no two posts within one topic can ever have the same date. If you expect this to happen, the query must be changed to account for it.

SQL - Nested select statement?

I have 2 tables, ticket and ticket_custom.
Here are how the tables are set up.
I have a web interface where I can change the state (value in the table ticket_custom) The web interface adds a new entry instead of updating the original entry.
ticket name value
1 state Ready for Final Verification
2 state Ready for Final Verification
1 state Verified
The last row is added
So I need to modify the queries.
SELECT p.value AS __color__,
id AS ticket, summary, component, version, c.value AS state, milestone, t.type AS type,
owner, status,
time AS created,
changetime AS _changetime, description AS _description,
reporter AS _reporter
FROM ticket t, ticket_custom c
LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' AND id = c.ticket
WHERE status <> 'closed' AND id = c.ticket
ORDER BY CAST(p.value AS int), milestone, t.type, time, c.ticket
The query now returns both entries. I tried to add a nested select in the where clause.
SELECT g.ticket
FROM ticket_custom g
WHERE g.ticket = id
ORDER BY g.ticket DESC LIMIT 1
So -
SELECT p.value AS __color__,
id AS ticket, summary, component, version, c.value AS state, milestone, t.type AS type,
owner, status,
time AS created,
changetime AS _changetime, description AS _description,
reporter AS _reporter
FROM ticket t, ticket_custom c
LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' AND id = c.ticket
WHERE status <> 'closed' AND id = c.ticket and (
SELECT g.ticket
FROM ticket_custom g
WHERE g.ticket = id
ORDER BY g.ticket DESC LIMIT 1 )
ORDER BY CAST(p.value AS int), milestone, t.type, time, c.ticket
Clearly I'm doing something wrong.
This appears to be more of a design issue than a query issue. While it is possible to return only a single record from the ticket_custom table there is not a way to determine which record that will be. In you sample table ticket 1 has a value of "Ready for..." and "Verified" but nothing that shows which happened first. Logically, the "Ready for..." happened first.
The easiest way for you to fix this issue would be to add a timestamp or incrementing ID field. Then your subquery could select the most recent entry (latest timestamp or highest ID).
Assuming at least one ticket, you could do this instead:
SELECT MAX(g.ticket)
FROM ticket_custom g
WHERE g.ticket=id
You can convert that to a JOIN or nested SELECT etc.
so change id=c.ticket id=MAX(c.ticket)
but check your WHERE & LEFT JOIN there's some strange stuff in there.
Don't make your database schema dynamic (i.e. "table-driven"). It isn't a sensible design pattern (I know from experience). It saves only a little effort upfront in creating additional attributes, but incurs additional overhead thereafter, both in writing queries and in the database processing required to execute them.
Just add a state id column to the ticket table and update it when the state changes. Create a reference table to store the state names. Then your queries become quite simple, and requires less effort for database engine to do an indexed join to a small reference table.

MySQL - Combining questions and answers from multiple transactions

I have the following tables within a database, that I am using to store the results of surveys:
Each time I speak to someone at a store (read Shop), I create a new transaction, with a date/time (tblTransaction.Created). Each transaction can have many question answers associated with it.
My problem is that 2 transactions could both contain different answers to the same question and I am trying to create an SQL query/procedure to return only the latest question answers for a given store.
Here's an example:
I speak with someone at Some Shop Plc. and create a transaction on the 01/01/09 (transaction ID 1). In this transaction, I ask QuestionIDs 1 and 2. Then on the 10/01/09 I speak to them again, creating a new transaction (transaction ID 2) and answer questions 2 and 3.
I want to be able to show the list of latest answers; Question 1 from the first transaction and questions 2 and 3 from the second transaction.
SELECT
S.StoreID,
S.BranchName,
A.QuestionID,
T.Created,
A.*
FROM
tblStore S
INNER JOIN tblTransaction T ON
T.StoreID = S.StoreID
INNER JOIN tblAnswer A ON
A.TransactionID = T.TransactionID AND
A.StoreID = S.StoreID
WHERE NOT EXISTS
(
SELECT
T2.StoreID,
A2.QuestionID,
T2.TransactionID,
T2.CreatedDate
FROM
tblTransaction T2
INNER JOIN tblAnswer A2 ON
A2.TransactionID = T2.TransactionID AND
A2.StoreID = T2.StoreID
WHERE
T2.StoreID = T.StoreID AND
A2.QuestionID = A.QuestionID AND
T2.CreatedDate > T.CreatedDate
)
You can also do this by LEFT OUTER JOINing the subquery on the same criteria as in the WHERE clause and looking for a NULL value in it or you can remove the TransactionID from the subquery use a MAX() on the CreatedDate and look for a match that way with an INNER JOIN.
Keep in mind that this may not act how you are expecting if you have multiple transactions for the same store with the same created date. You may need to add an additional criteria there based on your business rules around that situation.