Filtering in join query - crystal-reports

Using crystal reports version 14, MS sql server 2008
I am joining two tables and I need to filter in the join, so if a certain value exists in one of the table, I want to join to that record, if it does not exist, I want to have a null-record. I.e:
select * from sample left outer join test
on(sample.sample_number=test.sample_number and test.name='PREP')
I can run that in Sql server studio and get exactly what I want
What I can get in crystal reports is
select * from sample left outer join test
on(sample.sample_number=test.sample_number)
where test.name='PREP'
In the latter case, rows where test.name='PREP' does not exist will be removed and if there are samples that have no test.name='PREP', those samples will be removed.
Are there any ways I can do this in CR 14?
dummy tables:
Sample
sample_number,name
1,A
2,B
3,C
Test
sample_number,name
1,PREP
1,SOMETHING
2,SOMETHING
3,SOMETHING_ELSE
3,PREP
What I want:
1,A,1,PREP
2,B,NULL,NULL
3,C,3,PREP
(of course there are more fields in the tables and a selection of which fields, but this should illustrate what I want)
I know I can make views and query them directly in crystal, but if possible, I would avoid doing that.

Bah, found it:
Database expert - add table, select data source, add command. Then a custom sql can be added.

Related

Converting complex query with inner join to tableau

I have a query like this, which we use to generate data for our custom dashboard (A Rails app) -
SELECT AVG(wait_time) FROM (
SELECT TIMESTAMPDIFF(MINUTE,a.finished_time,b.start_time) wait_time
FROM (
SELECT max(start_time + INTERVAL avg_time_spent SECOND) finished_time, branch
FROM mytable
WHERE name IN ('test_name')
AND status = 'SUCCESS'
GROUP by branch) a
INNER JOIN
(
SELECT MIN(start_time) start_time, branch
FROM mytable
WHERE name IN ('test_name_specific')
GROUP by branch) b
ON a.branch = b.branch
HAVING avg_time_spent between 0 and 1000)t
GROUP BY week
Now I am trying to port this to tableau, and I am not being able to find a way to represent this data in tableau. I am stuck at how to represent the inner group by in a calculated field. I can also try to just use a custom sql data source, but I am already using another data source.
columns in mytable -
start_time
avg_time_spent
name
branch
status
I think this could be achieved new Level Of Details formulas, but unfortunately I am stuck at version 8.3
Save custom SQL for rare cases. This doesn't look like a rare case. Let Tableau generate the SQL for you.
If you simply connect to your table, then you can usually write calculated fields to get the information you want. I'm not exactly sure why you have test_name in one part of your query but test_name_specific in another, so ignoring that, here is a simplified example to a similar query.
If you define a calculated field called worst_case_test_time
datediff(min(start_time), dateadd('second', max(start_time), avg_time_spent)), which seems close to what your original query says.
It would help if you explained what exactly you are trying to compute. It appears to be some sort of worst case bound for avg test time. There may be an even simpler formula, but its hard to know without a little context.
You could filter on status = "Success" and avg_time_spent < 1000, and place branch and WEEK(start_time) on say the row and column shelves.
P.S. Your query seems a little off. Don't you need an aggregation function like MAX or AVG after the HAVING keyword?

Transact-SQL Ambiguous column name

I'm having trouble with the 'Ambiguous column name' issue in Transact-SQL, using the Microsoft SQL 2012 Server Management Studio.
I´ve been looking through some of the answers already posted on Stackoverflow, but they don´t seem to work for me, and parts of it I simply don´t understand or loses the general view of.
Executing the following script :
USE CDD
SELECT Artist, Album_title, track_title, track_number, Release_Year, EAN_code
FROM Artists AS a INNER JOIN CD_Albumtitles AS c
ON a.artist_id = c.artist_id
INNER JOIN Track_lists AS t
ON c.title_id = t.title_id
WHERE track_title = 'bohemian rhapsody'
triggers the following error message :
Msg 209, Level 16, State 1, Line 3
Ambiguous column name 'EAN_code'.
Not that this is a CD database with artists names, album titles and track lists. Both the tables 'CD_Albumtitles' and 'Track_lists' have a column, with identical EAN codes. The EAN code is an important internationel code used to uniquely identify CD albums, which is why I would like to keep using it.
You need to put the alias in front of all the columns in your select list and your where clause. You're getting that error because one of the columns you have currently is coming from multiple tables in your join. If you alias the columns, it will essentially pick one or the other of the tables.
SELECT a.Artist,c.Album_title,t.track_title,t.track_number,c.Release_Year,t.EAN_code
FROM Artists AS a INNER JOIN CD_Albumtitles AS c
ON a.artist_id = c.artist_id
INNER JOIN Track_lists AS t
ON c.title_id = t.title_id
WHERE t.track_title = 'bohemian rhapsody'
so choose one of the source tables, prefixing the field with the alias (or table name)
SELECT Artist,Album_title,track_title,track_number,Release_Year,
c.EAN_code -- or t.EAN_code, which should retrieve the same value
By the way, try to prefix all the fields (in the select, the join, the group by, etc.), it's easier for maintenance.

Tableau Extract API with multiple tables in a database

I am currently experimenting with Tableau Extract API to generate some TDE from the tables I have in a PostgreSQL database. I was able to write a code to generate the TDE from single table, but I would like to do this for multiple joined tables. To be more specific, if I have two tables that are inner joined by some field, how would I generate the TDE for this?
I can see that if I am working with small number of tables, I could use a SQL query with JOIN clauses to create a one gigantic table, and generate the TDE from that table.
>> SELECT * FROM table_1 INNER JOIN table_2
INTO new_table_1
ON table_1.id_1 = table_2.id_2;
>> SELECT * FROM new_table_1 INNER JOIN TABLE_3
INTO new_table_2
ON new_table_1.id_1 = table_3.id_3
and then generate the TDE from new_table_2.
However, I have some tables that have over 40 different fields, so this could get messy.
Is this even a possibility with current version of the API?
You can read from as many tables or other sources as you want. Or use complex query with lots of joins, or create a view and read from that. Usually, creating a view is helpful when you have a complex query joining many tables.
The data extract API is totally agnostic about how or where you get the data to feed it -- the whole point is to allow you to grab data from unusual sources that don't have pre-built drivers for Tableau.
Since Tableau has a Postgres driver and can read from it directly, you don't need to write a program with the data extract API at all. You can define your extract with Tableau Desktop. If you need to schedule automated refreshes of the extract, you can use Tableau Server or its tabcmd command.
Many thanks for your replies. I am aware that I could use Tableau Desktop to define my extract. In fact, I have done this many times before. I am just trying to create the extracts using the API, because I need to create some calculated fields, which is near impossible to create using the Tableau Desktop.
At this point, I am hesitant to use JOINs in the SQL query because the resulting table would look too complicated to comprehend (some of these tables also have same field names).
When you say that I could read from multiple tables or sources, does that mean with the Tableau Extract API? At this point, I cannot find anywhere in this API that accommodates multiple sources. For example, I know that when I use multiple tables in the Tableau Desktop, there are icons on the left hand side that tells me that the extract is composed of multiple tables. This just doesn't seem to be happening with the API, which leaves me stranded. Anyways, thank you again for your replies.
Going back to the topic, this is something that I tried few days ago on my python code
try:
tdefile= tde.Extract("extract.tde")
except:
os.remove("extract.tde")
tdefile = tde.Extract("extract.tde")
tableDef = tde.TableDefinition()
# Read each column in table and set the column data types using tableDef.addColumn
# Some code goes here...
for eachTable in tableNames:
tableAdd = tdeFile.addTable(eachTable, tableDef)
# Use SQL query to retrieve bunch_of_rows from eachTable
for some_row in bunch_of_rows:
# Read each row in table, and set the values in each column position of each row
# Some code goes here...
tableAdd.insert(some_row)
some_row.close()
tdefile.close()
When I execute this code, I get the error that eachTable has to be called "Extract".
Of course, this code has its flaws, as there is no where in this code that tells how each table are being joined.
So I am little thrown off here, because it doesn't seem like I can use multiple tables unless I use JOINs to generate one table that contains everything.

Add GROUP BY clause to crystal report

I have a report with a query that used to contain a client-id for each item. The client (the boss) wanted multiple clients for each record. That was easy - replace the client-id field with a new table ItemClients(item-id, client-id) and join on item-id.
The problem is now the reports - of course each item is duplicated for each time there is a client, BUT i WANT ONLY ONE COPY OF THE ITEM IN THE REPORT - irrespective of how many clients there are to an item. Also, there is the ability to filter the report by client, which I can do fine in MySql and worked fine in the previous single-client version.
My solution is to add a group by item-id clause to the query (MySql allows this). The problem is how to add the group by clause to the report. Any attempt to group gets interpreted as a report grouping, which I don't want. I tried to make the whole query as a command, which worked for a while, but now the whole report blows up, crashing my web server.
Any insights would be helpful. thanks.
(edit)
Here's the (hybrid) code in the command, the GROUP BY clause was added by me, the rest was scraped from crystal's show sql command and modified. (btw, this is a sub-report)
SELECT `ITEM`.`Date`, `ITEM`.`Started`, `ITEM`.`Stopped`, `TERM`.`Terminal`, `ITEM`.`TonnesLoaded`, `ITEM`.`LoadID`,
`ITEM`.`TotalLoaded`, `ITEM`.`ToGo`, `ITEM`.`OrderId`,
`COM`.`Commodity`,
`berths1`.`Berth`,
`CQ`.`LotNo`, `CQ`.`CategoryID`,
`IC`.`ClientId`
FROM `berths` `berths1`
INNER JOIN `Items` `ITEM` ON `berths1`.`BerthID`=`ITEM`.`BerthID`
INNER JOIN `terminals` `TERM` ON `berths1`.`TerminalID`=`TERM`.`TerminalID`
INNER JOIN `Quantities` `CQ` ON `ITEM`.`ItemId`=`CQ`.`ItemId`
AND `ITEM`.`OrderId`=`CQ`.`OrderId`
INNER JOIN `commodities` `COM` ON `CQ`.`CommodityID`=`COM`.`CommodityID`
LEFT OUTER JOIN `ItemClients` `IC` ON `CQ`.`OrderId`=`IC`.`OrderId`
AND `CQ`.`ItemId`=`IC`.`ItemId`
WHERE `ITEM`.`OrderId`={?Pm-details.OrderId}
AND ( {?Pm-?Category}=0 AND {?Pm-?ClientId}=0 )
OR (
`CQ`.CategoryID>0
AND `CQ`.CategoryID = {?Pm-?Category}
AND ( {?Pm-?ClientId}=0 OR IC.ClientId = {?Pm-?ClientId} )
)
OR ( {?Pm-?ClientId}>0 AND IC.ClientId = {?Pm-?ClientId} AND {?Pm-?Category}=0 )
GROUP BY `ITEM`.`ItemId`
ORDER BY `ITEM`.`Date`, `ITEM`.`Started`, `ITEM`.`LoadID`

Link tables when one column is padded with 0's in Crystal Reports

I have a database that has two tables that need to be linked, but in one table the data is padded with zeros. For example, the tables may look like this:
CUSTOMER.CUSTNUM = 00000000123456
CUSTOMERPHONE.CUSTNUM = 123456
I can't figure out how to get these tables to properly join.
What I'm trying to do now is trick Crystal Reports into specifying the Join clause by adding the following to the selection expert:
Right ({CUSTOMER.CUSTNUM}) = {CUSTOMERPHONE.CUSTNUM}
That's not working though, and I get no records at all in my report.
Any ideas?
Crystal doesn't like heterogeneous joins.
Options:
use a command object, which will give you more control over the linkage
create a SQL Expression that performs the desired concatination; link fields in the record-selection formula
use a subreport for the linked table
alter the table to make the data types compatible
create a SQL view that performs the joins
First thing, why does CUSTOMER.CUSTNUM have leading zeros in the first place? It seems to me that it should be a NUMERIC data type instead of a VARCHAR. CUSTNUM should be consistent in all of the tables. Just a thought.
Anyway, to answer your question, you could try creating a SQL Command in Crystal to join the two tables. In the join, just use your database's function for converting from a varchar to a number. For example, in Access you could do:
SELECT *
FROM `Customer`
LEFT OUTER JOIN `Orders` ON `Orders`.`Numeric Customer ID` = CLng(`Customer`.`Varchar Customer ID`)
If fastest performance isn't an issue, you can accomplish this using Select Expert. I think the problem is your formula.
Try changing your formula from this:
{CUSTOMERPHONE.CUSTNUM} = Right({CUSTOMER.CUSTNUM})
to this:
{CUSTOMERPHONE.CUSTNUM} = Right({CUSTOMER.CUSTNUM}, Length({CUSTOMERPHONE.CUSTNUM}))