how to achieve Tableau from SQL statement - tableau-api

Please can anyone help out on how to achieve sql statement in tableau. I have a table in Tableau that contains ID name smkoes SmokeCessRef ward etc as the dimension in tableau. In SQL i query the table as follows:
SELECT
count(Distinct ID) as TotSmokeExcl
FROM IP
WHERE
(Smokes in ('Yes') and SmokeCessRef in ('No'))
OR
(Smokes in ('Yes') and SmokeCessRef in ('No') and [Disch/LastWard] in ('Camp','House'))
How can i do this in tableau. or what process do i need to do to achieve this in Tableau

Create a calculated field with similar logic to that which you have in SQL.
([Smokes] = 'Yes' AND [SmokeCessRef] = 'No') OR
([Smokes] = 'Yes' AND [SmokeCessRef] = 'No' AND ([Disch/LastWard] = 'Camp' OR [Disch/LastWard] = 'House'))
Then put the calculated field in the filter card and set it to 'True'.
As an aside, your logic doesn't completely make sense. For instance, you are going to return all (Smokes in ('Yes') and SmokeCessRef in ('No')), so the second part (Smokes in ('Yes') and SmokeCessRef in ('No') and [Disch/LastWard] in ('Camp','House')) is useless.

Related

Use postgresql query results to form another query

I am trying to select from one table using the select result from another table. I can run this in two queries but would like to optimize it into just one.
First query.. Select ids where matching other id
select id from lookuptable where paid = '547'
This results in something like this
6316352
6316353
6318409
6318410
6320468
6320469
6320470
6322526
6322527
6324586
6324587
6326648
I would like to then use this result to make another selection. I can do it manually like below. Note, there could be many rows with these values so I've been using a IN statement
select * from "othertable" where id in (6316352,6316353,6318409,6318410,6320468,6320469,6320470,6322526,6322527,6324586,6324587,6326648);
select
ot.*
from
"othertable" as ot
join
lookuptable as lt
on
ot.id = lt.id
where
lt.paid = '547'
The IN operator supports not just value lists but also subqueries, so you can literally write
select * from "othertable" where id in (select id from lookuptable where paid = '547');

Conditional WHERE clause in KDB?

Full Query:
{[tier;company;ccy; startdate; enddate] select Deal_Time, Deal_Date from DEALONLINE_REMOVED where ?[company = `All; 1b; COMPANY = company], ?[tier = `All;; TIER = tier], Deal_Date within(startdate;enddate), Status = `Completed, ?[ccy = `All;1b;CCY_Pair = ccy]}
Particular Query:
where ?[company = `All; 1b; COMPANY = company], ?[tier = `All; 1b; TIER = tier],
What this query is trying to do is to get the viewstate of a dropdown.
If there dropdown selection is "All", that where clause i.e. company or tier is invalidated, and all companies or tiers are shown.
I am unsure if the query above is correct as I am getting weird charts when displaying them on KDB dashboard.
What I would recommend is to restructure your function to make use of the where clause using functional qSQL.
In your case, you need to be able to filter based on certain input, if its "All" then don't filter else filter on that input. Something like this could work.
/Define sample table
DEALONLINE_REMOVED:([]Deal_time:10#.z.p;Deal_Date:10?.z.d;Company:10?`MSFT`AAPL`GOOGL;TIER:10?`1`2`3)
/New function which joins to where clause
{[company;tier]
wc:();
if[not company=`All;wc:wc,enlist (=;`Company;enlist company)];
if[not tier=`All;wc:wc,enlist (=;`TIER;enlist tier)];
?[DEALONLINE_REMOVED;wc;0b;()]
}[`MSFT;`2]
If you replace the input with `All you will see that everything is returned.
The full functional select for your query would be as follows:
whcl:{[tier;company;ccy;startdate;enddate]
wc:(enlist (within;`Deal_Date;(enlist;startdate;enddate))),(enlist (=;`Status;enlist `Completed)),
$[tier=`All;();enlist (=;`TIER;enlist tier)],
$[company=`All;()enlist (=;`COMPANY;enlist company)],
$[ccy=`All;();enlist (=;`CCY_Pair;enlist ccy)];
?[`DEALONLINE_REMOVED;wc;0b;`Deal_Time`Deal_Date!`Deal_Time`Deal_Date]
}
The first part specifies your date range and status = `Completed in the where clause
wc:(enlist (within;`Deal_Date;(enlist;startdate;enddate))),(enlist (=;`Status;enlist `Completed)),
Next each of these conditionals checks for `All for the TIER, COMPANY and CCY_Pair column filtering. It then joins these on to the where clause when a specific TIER, COMPANY or CCY_Pair are specified. (otherwise an empty list is joined on):
$[tier=`All;();enlist (=;`TIER;enlist tier)],
$[company=`All;();enlist (=;`COMPANY;enlist company)],
$[ccy=`All;();enlist (=;`CCY_Pair;enlist ccy)];
Finally, the select statement is called in its functional form as follows, with wc as the where clause:
?[`DEALONLINE_REMOVED;wc;0b;`Deal_Time`Deal_Date!`Deal_Time`Deal_Date]

Add a single field to model using raw SQL

I'm developing an extension for TYPO3 CMS 8.7.8. I'm using query->statement() to select all fields from a single table, plus 1 field from another table. I get a QueryResult with the proper models and I would like to have that 1 extra field added to them. Is that possible?
You can do SQL queries with the ->statement(...) method and in that, use normal JOIN commands
From the documentation
$result = $query->statement('SELECT * FROM tx_sjroffers_domain_model_offer
WHERE title LIKE ? AND organization IN ?', array('%climbing%', array(33,47)));
So you can do JOINs on whatever table you want to (also code from the documentation)
LEFT JOIN tx_blogexample_person
ON tx_blogexample_post.author = tx_blogexample_person.uid
But you will end up with the raw data from the mysql query. If you want to transform it into a object, use the Property Mapper
You can use JOIN in your sql statments like below.
$query = $this->createQuery();
$sql = 'SELECT single.*,another.field_anme AS fields_name
FROM
tx_single_table_name single
JOIN
tx_another_table_name another
ON
single.fields = another.uid
WHERE
O.deleted = 0
AND O.hidden=0
AND O.uid=' . $orderId;
return $query->statement($sql)->execute();

Compare two tables in different databases and change one table

I have two databases in the same sql instance. One is backup2 which is a restored backup of my original database.
Database Table
Original.Payments
Backup2.Payments
I have two fields in each that I need to compare:
PaymentsId - guid
IsProcessed - bit
I need to compare the PaymentsId in each and if the payment exists in Backup2 and is marked Processed, I need to mark the Original.Payments.Backup as true.
I have the first part of the query done but I'm not sure how to link it to the Original database:
SELECT [PaymentId]
,[CorporationId]
,[IsProcessed]
FROM [Backup2].[Web].[Payment]
WHERE CorporationId = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
and IsProcessed = 'true'
This gives me my list of payments but I need to compare those to the original database and I'm not sure how.
Where do I go from here?
Thank you!
you can use update with join syntax
update OP
set IsProcessed = 'true'
FROM [Original].[Payments].[Backup] OP
JOIN [Backup2].[Web].[Payment] BP
on OP.PaymentId = BP.PaymentId
and BP.corporationId = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
and BP.IsProcessed ='true'
and OP.corporationId = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
This should be a start
SELECT [p1].[PaymentId]
,[p1].[CorporationId]
,[p1].[IsProcessed]
FROM [Backup2].[Web].[Payment] as [p1]
JOIN [Original].[Web].[Payment] as [p2]
on [p2].[CorporationId] = [p1].[CorporationId]
AND [p2].[PaymentId] = [p1].[PaymentId]
AND [p1].[CorporationId] = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
and [p1].[IsProcessed =]'true'

Select most reviewed courses starting from courses having at least 2 reviews

I'm using Flask-SQLAlchemy with PostgreSQL. I have the following two models:
class Course(db.Model):
id = db.Column(db.Integer, primary_key = True )
course_name =db.Column(db.String(120))
course_description = db.Column(db.Text)
course_reviews = db.relationship('Review', backref ='course', lazy ='dynamic')
class Review(db.Model):
__table_args__ = ( db.UniqueConstraint('course_id', 'user_id'), { } )
id = db.Column(db.Integer, primary_key = True )
review_date = db.Column(db.DateTime)#default=db.func.now()
review_comment = db.Column(db.Text)
rating = db.Column(db.SmallInteger)
course_id = db.Column(db.Integer, db.ForeignKey('course.id') )
user_id = db.Column(db.Integer, db.ForeignKey('user.id') )
I want to select the courses that are most reviewed starting with at least two reviews. The following SQLAlchemy query worked fine with SQlite:
most_rated_courses = db.session.query(models.Review, func.count(models.Review.course_id)).group_by(models.Review.course_id).\
having(func.count(models.Review.course_id) >1) \ .order_by(func.count(models.Review.course_id).desc()).all()
But when I switched to PostgreSQL in production it gives me the following error:
ProgrammingError: (ProgrammingError) column "review.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT review.id AS review_id, review.review_date AS review_...
^
'SELECT review.id AS review_id, review.review_date AS review_review_date, review.review_comment AS review_review_comment, review.rating AS review_rating, review.course_id AS review_course_id, review.user_id AS review_user_id, count(review.course_id) AS count_1 \nFROM review GROUP BY review.course_id \nHAVING count(review.course_id) > %(count_2)s ORDER BY count(review.course_id) DESC' {'count_2': 1}
I tried to fix the query by adding models.Review in the GROUP BY clause but it did not work:
most_rated_courses = db.session.query(models.Review, func.count(models.Review.course_id)).group_by(models.Review.course_id).\
having(func.count(models.Review.course_id) >1) \.order_by(func.count(models.Review.course_id).desc()).all()
Can anyone please help me with this issue. Thanks a lot
SQLite and MySQL both have the behavior that they allow a query that has aggregates (like count()) without applying GROUP BY to all other columns - which in terms of standard SQL is invalid, because if more than one row is present in that aggregated group, it has to pick the first one it sees for return, which is essentially random.
So your query for Review basically returns to you the first "Review" row for each distinct course id - like for course id 3, if you had seven "Review" rows, it's just choosing an essentially random "Review" row within the group of "course_id=3". I gather the answer you really want, "Course", is available here because you can take that semi-randomly selected Review object and just call ".course" on it, giving you the correct Course, but this is a backwards way to go.
But once you get on a proper database like Postgresql you need to use correct SQL. The data you need from the "review" table is just the course_id and the count, nothing else, so query just for that (first assume we don't actually need to display the counts, that's in a minute):
most_rated_course_ids = session.query(
Review.course_id,
).\
group_by(Review.course_id).\
having(func.count(Review.course_id) > 1).\
order_by(func.count(Review.course_id).desc()).\
all()
but that's not your Course object - you want to take that list of ids and apply it to the course table. We first need to keep our list of course ids as a SQL construct, instead of loading the data - that is, turn it into a derived table by converting the query into a subquery (change the word .all() to .subquery()):
most_rated_course_id_subquery = session.query(
Review.course_id,
).\
group_by(Review.course_id).\
having(func.count(Review.course_id) > 1).\
order_by(func.count(Review.course_id).desc()).\
subquery()
one simple way to link that to Course is to use an IN:
courses = session.query(Course).filter(
Course.id.in_(most_rated_course_id_subquery)).all()
but that's essentially going to throw away the "ORDER BY" you're looking for and also doesn't give us any nice way of actually reporting on those counts along with the course results. We need to have that count along with our Course so that we can report it and also order by it. For this we use a JOIN from the "course" table to our derived table. SQLAlchemy is smart enough to know to join on the "course_id" foreign key if we just call join():
courses = session.query(Course).join(most_rated_course_id_subquery).all()
then to get at the count, we need to add that to the columns returned by our subquery along with a label so we can refer to it:
most_rated_course_id_subquery = session.query(
Review.course_id,
func.count(Review.course_id).label("count")
).\
group_by(Review.course_id).\
having(func.count(Review.course_id) > 1).\
subquery()
courses = session.query(
Course, most_rated_course_id_subquery.c.count
).join(
most_rated_course_id_subquery
).order_by(
most_rated_course_id_subquery.c.count.desc()
).all()
A great article I like to point out to people about GROUP BY and this kind of query is SQL GROUP BY techniques which points out the common need for the "select from A join to (subquery of B with aggregate/GROUP BY)" pattern.