Create Table based on distinct attributes in SQL - sql

I need to create a new table in MS Access based on a specific attribute. To simplify the problem, I will illustrate the desired result with a dummy table:
As you can see, I have different flowers (distinguished by their numbers - Flowerno), along with their attributes and values. The new table should be based on the distinct pairs of Attribute "color" and its Value. So in this example, we have two pairs: (color, red) and (color, yellow). Now, each pair belongs to a specific Flowerno and its other attributes like shape and fragrance. I would like to create a table with the attribute color as the main focus and present its other attributes of the same flower:
In other words, I want to list all colors along with the attributes and values distinctively in three different columns.

You need code that will do a lookup of color associated with flowerno and return that value for use in sorting/grouping. Could try calculating a field with DLookup:
GrpColor: DLookup("value", "table","attribute='color' AND flowerno=" & [flowerno])
Unfortunately, domain aggregate function can cause slow performance in query. Alternative would use subquery:
SELECT table.*, Q.GrpColor FROM table
INNER JOIN (SELECT FlowerNo, [Value] AS GrpColor
FROM table WHERE attribute = "color") AS Q
ON table.FlowerNo = Q.FlowerNo
WHERE Attribute<>"color";

Related

PostgreSQL/Metabase: How to create variable to filter by multiple numbers

I would like to filter by multiple ids (e.g. item ids of purchases). The following line of code does not seem to do the trick either for number or text variables (e.g. user names). How should I write this line of code so in the filtering field I could type my values separated by a comma and look for entries that contain either of the item ids I have provided? How would that line of code differ if wanting to apply a filter by a text variable instead (i.e. user name)?
[[where "User name" like concat('%',{{user_name}},'%')]]
Use a field filter parameter, mapping it to the id column and it's respective table
Then structure your query like below:
select * from profiles where user_name ({{PARAM}})
Documentation: https://www.metabase.com/learn/sql-questions/field-filters

Get column names stored in a different table

I have a table that has just a code for the individual column name like "A1G", "Z8H" etc.
This table is a really huge table. Therefore it would not help to manually add the alias name in the SELECT Statement like.
The description for each column code is stored in a different table:
Now I would like to SELECT * from the first table but with the right column header name.
This is stored in the second table within the filters Schema = 'ABC' and Table = 'A'.
That would be desired output:
How would you do that in SQL?
How can I change the column name?
You would be better off just creating a view with all the columns aliased to your preferred names. Once that's done you can select from the view and get the data back with the headings you want.
Look into Inner Join
Or Left Join.

SSRS Dropdown for column items

I've built a SSRS report using a SQL query for the Dataset1. I'm trying to build a parameter that gives the users a dropdown list. I ended up creating a Dataset2 to get distinct values for the parameter Label and then use Dataset1 for the actual value (allowing for multiple values).
EDITING PER Request:
Dataset1 query:
SELECT vu_SOPWork_HistoryUnion.Type
,vu_SOPWork_HistoryUnion.SOPTYPE
,vu_SOPWork_HistoryUnion.SOPNUMBE
,vu_SOPWork_HistoryUnion.Date_Document
,vu_SOPWork_HistoryUnion.ExtendedPrice
,IV00101.ITEMNMBR
,IV00101.USCATVLS_2 AS Family
,IV00101.USCATVLS_3 AS Product
,vu_SOPWork_HistoryUnion.VoidStatus
,RM00101.CUSTCLAS
,GL00100.MNACSGMT
,vu_SOPWork_HistoryUnion.BillTo_CustNum
,vu_SOPWork_HistoryUnion.BillTo_CustName
,vu_SOPWork_HistoryUnion.sales_territory
,vu_SOPWork_HistoryUnion.ITEMDESC
FROM (
(
test.dbo.vu_SOPWork_HistoryUnion vu_SOPWork_HistoryUnion INNER JOIN test.dbo.IV00101 IV00101 ON vu_SOPWork_HistoryUnion.ITEMNMBR = IV00101.ITEMNMBR
) INNER JOIN test.dbo.RM00101 RM00101 ON vu_SOPWork_HistoryUnion.BillTo_CustNum = RM00101.CUSTNMBR
)
INNER JOIN test.dbo.GL00100 GL00100 ON IV00101.IVSLSIDX = GL00100.ACTINDX
Dataset2 Query:
SELECT DISTINCT IV00101.USCATVLS_2 AS FamilyNames
FROM test.dbo.IV00101
I would like to use the Dataset2 "FamilyNames" as the label options against Dataset1 "Family" values. Dataset2 gets the distinct values that I want to put in the drop down for the user to choose and then receive all rows that has that value in Dataset1 "Family". I'm an expert on not giving enough information. Hope this helps you help me. Thanks.
OK, do the following..
Create DataSet1 with the query as you have it now but append the following to the end of the query
WHERE USCATVLS_2 IN(#Family)
When you do this, the #Family parameter will be created automatically in your report, we'll get back to this later.
Create another dataset called Dataset2 (or a more sensible name like 'families' in this case) with the following simple query.
SELECT DISTINCT USCATVLS_2 FROM test.dbo.IV00101 ORDER BY USCATVLS_2
Edit the #Family parameter:
Set it to multi-value
Change the available values to be a query
Select your 2nd dataset as the datasource
Choose USCATVLS_2 as both the labels and values.
Create your report as normal with the tablix/matrix based on Dataset1.
Notes:
A few other things you might want to consider, but not required.
If a list of family names with some kind of ID is available in your database then I suggest you use that for your parameter list, you would also then have to edit the query in dataset1 to match. Remember that the parameter will contain whatever is in the column of the query that you chose as the value column in the dataset that populates the parameter list
Consider using aliases for table names in your queries rather than the full table names all the time, it makes the code more concise and easier to read.
Name your datasets according to what they contain or do, e.g. I would call Dataset2 'Families' or something similar as that is what it contains. When your reports get more complex it will make them easier to understand.

Creating a calculated field table based on data in separate tables

It is straight forward to create a calculated field in a table that uses data IN the table... due to the fact that the expression builder is straight forward to use. However, it appears to me that the expression builder for the calculated field only works with data IN the table;
i.e: expression builder in table MYTABLE works with fields FIELD1.MYTABLE, FIELD2.MYTABLE etc.
Inventory Problem
My problem is that I have two 'count' fields that result from my queries that apply to INPUTQUERY and OUTPUTQUERY (gives me a count of all input data added and a count of all output data added) and now I want to subtract the two to get a stock.
I can't link the table that was created from my query because it wont be able to continually update do the relationship itself, and thus i'm stuck either using the expression builder/SQL.
First question:
Is it possible to have the expression builder reference data from other tables?
i.e expressionbuilder for:
MAINTABLE CALCULATEDFIELD.MAINTABLE = INPUTSUM.INPUTTABLE - OUTPUTSUM.OUTPUTTABLE
(which gives a difference of the two)?
Second question:
if the above isn't possible, can I do this through an SQL code ?
i.e
SELECT(data from INPUTSUM)
FROM(INPUTTABLE)
-
SELECT(data from OUTPUTSUM)
FROM(OUTPUTTABLE)
Try this:
SELECT SUM(T.INPUTSUM) - SUM(T.OUTPUTSUM) AS RESULTSUM
FROM
(
SELECT INPUTSUM, 0 AS OUTPUTSUM
FROM INPUTTABLE
UNION
SELECT 0 AS INPUTSUM, OUTPUTSUM
FROM OUTPUTTABLE
) AS T

Can SQL determine which values from a set of possible column values do not exist?

I have a unique column. I also have a known set of elements that are possible values for the column. I need to know which of the possible values are not already in the table, and as such, are suitable for insertion.
Is this possible with SQL or is post processing required?
Currently, I am using the "in" operator to select all rows where the column value equals an element in my set. Then I remove all matched elements from my set via post processing.
Stick the allowed values in a temporary table allowed, then use a subquery using NOT IN:
SELECT *
FROM allowed
WHERE allowed.val NOT IN (
SELECT maintable.val
)
Some DBs will allow you to build up a table "in-place", instead of having to create a separate table. E.g. in PostgreSQL (any version):
SELECT *
FROM (
SELECT 'foo'
UNION ALL SELECT 'bar'
UNION ALL SELECT 'baz' -- etc.
) inplace_allowed
WHERE inplace_allowed.val NOT IN (
SELECT maintable.val
)
More modern versions of PostgreSQL (and perhaps other DBs) will let you use the slightly nicer VALUES syntax to do the same thing.
To do this entirely in SQL you will need to create a separate table with one column. Each row holds one value from the known set of elements. Assuming the table is called ElementList and the other table is called Existing:
SELECT * FROM ElementList WHERE Element NOT IN
(SELECT DISTINCT Element FROM Existing)
Depending on what database engine you're using you may be able to use a temporary table to create and hold the list without saving it permanently in the database. However, storing the list of allowed elements is valuable for constraining the Element column in the Existing table (and for presenting the user with allowed Elements in the user interface).