How do i get distinct value chart from the following table? [Qlik Sense] - qlikview

So the data table I use is like :
id
status
TimeCompleted
1
Done
02:04 PM
2
Done
02:04 PM
3
Failed
02:17 PM
3
Done
02:04 PM
If I try to make a chart for (Count)status(y axis) vs TimeCompleted(x axis), the x axis has duplicate values for 02:04 PM. I want the graph to show count 3 for 02:04 PM. How can I do it??
Writing distinct in the dimension doesnt help.
I am new to Qlik so need a little help on this problem. Thankyou.

Your dimension should be "TimeCompleted" field. Your expression should be
Count( distinct id )
That's it.

Related

Query with input parameter won't compile as a view

So I am trying to create a view that allows the user (from the front-end) query on it by specifying a specific date (in the form of a varchar/string). The view/query will then return data for the month of the specified date and also data for 13 months prior to it. When I run the following query and enter a valid 'string'/date , I am able to return results successfully. However, when I try to create a view with the same query, i am receiving the following error:
SQL Error: ORA-01027: bind variables not allowed for data definition operations
Below is the query:
SELECT person_name
, person_age
, person_dob
FROM person p
WHERE p.person_dob >= add_months(to_date(:par_date, 'yyyy-mm-dd'), -13);
Here is some sample data:
Person_Name Person_Age Person_DOB
Jon 18 01-01-1990
Jacob 21 09-04-1994
Heidi 28 04-02-2010
mark 30 05-02-2011
Helga 18 03-02-2015
Mike 18 01-02-1992
Larry 18 01-04-1993
I want to return the following result after specify :par_date as '2020-03-02'.
Person_Name Person_Age Person_DOB
Heidi 28 04-02-2010
mark 30 05-02-2011
Helga 18 03-02-2015
You unfortunately cannot do this. The closest you could come would be to create a table function, but that will be much less efficient than just selecting from the table with a 'WHERE' clause.
Ask Tom has a work around, but it is complex, much more work, and potentially very inneficient. Just use a 'WHERE' clause on the view or table
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9536277800346269502

SELECT from 50 columns

I have a table that has many columns around 50 columns that have datetime data that represent steps user takes when he/she do a procedure
SELECT UserID, Intro_Req_DateTime, Intro_Onset_DateTime, Intro_Comp_DateTime, Info_Req_DateTime, Info_Onset_DateTime, Info_Comp_DateTime,
Start_Req_DateTime, Start_Onset_DateTime, Start_Comp_DateTime,
Check_Req_DateTime, Check_Onset_DateTime, Check_Comp_DateTime,
Validate_Req_DateTime, Validate_Onset_DateTime, Validate_Comp_DateTime,
....
FROM MyTable
I want to find the Step the user did after certain datetime
example I want to find user ABC what the first step he did after 2 May 2019 17:25:36
I cannot use case to check this will take ages to code
is there an easier way to do that?
P.S. Thanks for everyone suggested redesigning the database.. not all databases can be redesigned, this database is for one of the big systems we have and it is been used for more than 20 years. redesigning is out of the equation.
You can use CROSS APPLY to unpivot the values. The syntax for UNPIVOT is rather cumbersome.
The actual query text should be rather manageable. No need for complicated CASE statements. Yes, you will have to explicitly list all 50 column names in the query text, you can't avoid that, but it will be only once.
SELECT TOP(1)
A.StepName
,A.dt
FROM
MyTable
CROSS APPLY
(
VALUES
('Intro_Req', Intro_Req_DateTime)
,('Intro_Onset', Intro_Onset_DateTime)
,('Intro_Comp', Intro_Comp_DateTime)
.........
) AS A (StepName, dt)
WHERE
MyTable.UserID = 'ABC'
AND A.dt > '2019-05-02T17:25:36'
ORDER BY dt DESC;
See also How to unpivot columns using CROSS APPLY in SQL Server 2012
The best way is to design your table with your action type and datetime that action was done. Then you can use a simple where clause to find what you want. The table should be like the table below:
ID ActionType ActionDatetime
----------- ----------- -------------------
1492 1 2019-05-13 10:10:10
1494 2 2019-05-13 11:10:10
1496 3 2019-05-13 12:10:10
1498 4 2019-05-13 13:10:10
1500 5 2019-05-13 14:10:10
But in your current solution, you should use UNPIVOT to get what you want. You can find more information in this LINK.

MAX Function Fails in SQL

I'm trying to get the MOST recent date that comes before tom_temp.Begin_Time out of tbl_Trim_history.Comp. The SQL I'm using is:
SELECT
Tom_Temp2.feeder,
Tom_Temp.CauseType,
Tom_Temp.RootCause,
Tom_Temp.Storm_Name_Thunder,
Tom_Temp.DeviceGroup,
tbl_Trim_History.[COMP],
Tom_Temp.[Begin_Time]
FROM Tom_Temp2
LEFT JOIN (Tom_Temp
LEFT JOIN tbl_Trim_History
ON Tom_Temp.feeder = tbl_Trim_History.CIRCUIT_ID)
ON Tom_Temp2.feeder = Tom_Temp.feeder
WHERE (((tbl_Trim_History.[COMP]) < [Tom_Temp].[Begin_Time]));
I'm having a hard time figuring out where I need to put my max() function in this statement in order to make sure I don't get back every single tbl_Trim_history.[COMP] that occurs prior to the tom_temp.Begin_Time date. I only want the most recent date from tbl_Trim_history.[COMP] that occurs BEFORE the tom_temp.begin_Time .... NOT every historical date record.
Any help you guys could give me would be awesome because I keep getting back sets that I can tell are not what I'm looking for / expecting.
Thanks everyone. I appreciate the feedback.
Edit in regard to the responses below:
Due to the character limits, I just edited the master post for you guys.
I can't really post the data as it is somewhat confidential, so the best I can do is give you an example. Also, this is access, but my background is MySQL. Sorry for the tags, I wasn't sure what was similar since the access tag just didn't seem to fit the question.
The Data being received are about 168 records. Someone pointed out that there is an inner join occurring here, but I wanted to indicate I'm actually using 3 different tables.
1 table contains my feeders,
Another contains a list of all outages that I am joining to using all my feeders contained in the first table
Then I have another table that contains all the trim history for each feeder. The outage table is joined to the trim table.
When I run the query above, I get data like this
feeder | comp | Begin_time
___________________________________________
123456 | 10/4/2012 | 3/3/2016 11:26:00AM
123456 | 10/17/2015 | 3/3/2016 11:26:00AM
456789 | 6/28/2008 | 9/20/2013 10:05AM
456789 | 12/1/2012 | 9/20/2013 10:05AM
456789 | 7/3/2013 | 9/20/2013 10:05AM
what I want is data like this:
feeder | comp | Begin_time
___________________________________________
123456 | 10/17/2015 | 3/3/2016 11:26:00AM
456789 | 7/3/2013 | 9/20/2013 10:05AM
where the comp date is the closest to date / time occuring BEFORE Begin_time date.
I tried this query:
SELECT Tom_Temp2.feeder, Tom_Temp.CauseType, Tom_Temp.RootCause, Tom_Temp.Storm_Name_Thunder, Tom_Temp.DeviceGroup, Max(tbl_Trim_History.COMP) AS MaxOfCOMP, Tom_Temp.Begin_Time
FROM Tom_Temp2
LEFT JOIN (Tom_Temp LEFT JOIN tbl_Trim_History ON Tom_Temp.feeder = tbl_Trim_History.CIRCUIT_ID) ON Tom_Temp2.feeder = Tom_Temp.feeder
GROUP BY Tom_Temp2.feeder, Tom_Temp.CauseType, Tom_Temp.RootCause, Tom_Temp.Storm_Name_Thunder, Tom_Temp.DeviceGroup, Tom_Temp.Begin_Time
HAVING (((Max(tbl_Trim_History.COMP))<[Tom_Temp].[Begin_Time]));
But of the 168 records I get back in my first query, I'm only getting back 20 records with this query.
The reason I know this is wrong is because some records are missing between the set of 168 and the set of 20. For example, I'd be missing any records for feeder 456789. However, I know this record should be returned because it's in my table of feeders that should be returned (Tom_Temp2).
After manually deleting unwanted rows of data, I know that I should get a record count of 85. So my most recent attempt to use the Max query is way off.

Search multiple columns for multiple variables and then split by variable name

Preface with the fact I'm a complete SQL noob, and I'm aware that this is supposedly quite a simple query however I can't find anything on here that has helped me. So thanks for your time.
I have several columns that have coded events happening to a person listed within them. And I want to search by the code (e.g. A106 or B465) to count the number of times an event has happened, no matter which column it is in. So essentially search all of the event columns and make a count of how many times 4 different events turn up, with the results split by the event code. What I have so far as my structure (which may or may not be right) is:
SELECT COUNT()
FROM EVENTSLOG
WHERE EVENT1 IN ('A106', 'A107', 'B465', 'E713') OR
EVENT2 IN ('A106', 'A107', 'B465', 'E713') OR
EVENT3 IN ('A106', 'A107', 'B465', 'E713') OR
EVENT4 IN ('A106', 'A107', 'B465', 'E713')
GROUP BY
I know this isn't much but I have about 100 other snippets that I've written, including trying to UNION all the columns (confused about keeping the associated primary key) every time I'm getting stuck onto how to split by the event code at the end.
Thanks :)
Update:
What I'm hoping for is to get something like
Event Code Number of Events
=========== =================
A106 554
A107 4233
B465 4196
E713 34
I am running the suggested code below but it is a huge data set (and I am actually searching 24 columns for 7 codes, and so far my query has been running for a very long time) - and I haven't had any output yet.
2nd edit
Okay just had the query results back from the suggested answer below.. and i got back the table outline I'm looking for but it is only giving a count of 1 for every code when I know there are more than that?
eg.
CODE CNT
==== ====
A105 1
A106 1
B465 1
E713 1
F432 1
F465 1
K364 1
Just do a union of all 4 columns:
select code, count(*) as cnt
from(
select event1 as code from log
union all
select event2 as code from log
union all
select event3 as code from log
union all
select event4 as code from log
)t
where code in('A106', 'A107', 'B465', 'E713')
group by code

Cumulative average number of records created for specific day of week or date range

Yeah, so I'm filling out a requirements document for a new client project and they're asking for growth trends and performance expectations calculated from existing data within our database.
The best source of data for something like this would be our logs table as we pretty much log every single transaction that occurs within our application.
Now, here's the issue, I don't have a whole lot of experience with MySql when it comes to collating cumulative sum and running averages. I've thrown together the following query which kind of makes sense to me, but it just keeps locking up the command console. The thing takes forever to execute and there are only 80k records within the test sample.
So, given the following basic table structure:
id | action | date_created
1 | 'merp' | 2007-06-20 17:17:00
2 | 'foo' | 2007-06-21 09:54:48
3 | 'bar' | 2007-06-21 12:47:30
... thousands of records ...
3545 | 'stab' | 2007-07-05 11:28:36
How would I go about calculating the average number of records created for each given day of the week?
day_of_week | average_records_created
1 | 234
2 | 23
3 | 5
4 | 67
5 | 234
6 | 12
7 | 36
I have the following query which makes me want to murderdeathkill myself by casting my body down an elevator shaft... and onto some bullets:
SELECT
DISTINCT(DAYOFWEEK(DATE(t1.datetime_entry))) AS t1.day_of_week,
AVG((SELECT COUNT(*) FROM VMS_LOGS t2 WHERE DAYOFWEEK(DATE(t2.date_time_entry)) = t1.day_of_week)) AS average_records_created
FROM VMS_LOGS t1
GROUP BY t1.day_of_week;
Halps? Please, don't make me cut myself again. :'(
How far back do you need to go when sampling this information? This solution works as long as it's less than a year.
Because day of week and week number are constant for a record, create a companion table that has the ID, WeekNumber, and DayOfWeek. Whenever you want to run this statistic, just generate the "missing" records from your master table.
Then, your report can be something along the lines of:
select
DayOfWeek
, count(*)/count(distinct(WeekNumber)) as Average
from
MyCompanionTable
group by
DayOfWeek
Of course if the table is too large, then you can instead pre-summarize the data on a daily basis and just use that, and add in "today's" data from your master table when running the report.
I rewrote your query as:
SELECT x.day_of_week,
AVG(x.count) 'average_records_created'
FROM (SELECT DAYOFWEEK(t.datetime_entry) 'day_of_week',
COUNT(*) 'count'
FROM VMS_LOGS t
GROUP BY DAYOFWEEK(t.datetime_entry)) x
GROUP BY x.day_of_week
The reason why your query takes so long is because of your inner select, you are essentialy running 6,400,000,000 queries. With a query like this your best solution may be to develop a timed reporting system, where the user receives an email when the query is done and the report is constructed or the user logs in and checks the report after.
Even with the optimization written by OMG Ponies (bellow) you are still looking at around the same number of queries.
SELECT x.day_of_week,
AVG(x.count) 'average_records_created'
FROM (SELECT DAYOFWEEK(t.datetime_entry) 'day_of_week',
COUNT(*) 'count'
FROM VMS_LOGS t
GROUP BY DAYOFWEEK(t.datetime_entry)) x
GROUP BY x.day_of_week