Parameters being passed in are in wrong format for table - sql

I have a query whereby parameters are being passed in in the format 'GRB','MIN','OSH' and so on. These are called "Divisions". They may be passed in singly or in a list of any number of them. These are used in one of the tables n a report.
The problem is that the table I am going to read other divisions are going to have them in numerical format. so GRB = 02, MIN=04 and OSH = 08. There are 12 different values.
So in essence, the SSRS report might pass in all these for an "IN" statement. They have to be presented in this manner.
I need to find a way to convert all of these alphanumeric codes into their corresponding numeric codes.
Main query with alphanumeric:
dbo.TQMNCR.PlantID IN (#PlantID)
Temp table with (hopefully) corresponding numeric values:
ProdTable.DIMENSION2_ in (????????)

Presuming that dbo.TQMNCR has a PlantNumber column for the numeric key, you could use a join like this.
SELECT ...
FROM dbo.TQMNCR AS Source
INNER JOIN ProdTable AS Mapping
ON Mapping.DIMENSION2_ = Source.THE_NUMERIC_KEY_COLUMN_YOU_SPEAK_OF
WHERE Mapping.PlantID IN (#PlantID)
Alternatively, if you don't want to use a permanent table to map them, you can also use a common table expression (numerous other options).
WITH Mapping_CTE AS (
SELECT 'GRB' AS PlantID, '02' AS PlantNumber
UNION ALL
SELECT 'MIN' AS PlantID, '04' AS PlantNumber
UNION ALL
...
)
SELECT ...
FROM dbo.TQMNCR AS Source
INNER JOIN Mapping_CTE AS Mapping
ON Mapping.PlantNumber = Source.THE_NUMERIC_KEY_COLUMN_YOU_SPEAK_OF
WHERE Mapping.PlantID IN (#PlantID)

Related

How do I display varchar as percentage, while aliasing, and linking multiple tables using the same variable?

I have four CSV tables of census data. I’m trying to develop a query that will allow me to search one variable which exists in all four tables (a FIPS code). Also, display selected data from only certain columns of each table, while aliasing the headers, and modifying some of the results as a percentage, and/or money.
Table details:
The respective table names are DP02, DP03, DP04, and DP05.
All four tables can be linked by the GEO_id2 variable.
Each table has close to one hundred rows, or more.
Aside from the GEO_id headers, the remaining headers have names like HC03_VC01, 02, etc.
All of the data is in VARCHAR format. The data consists of numbers representing different types of variables: 63.4 in table stands for 63.4%, 47721 stands for $47,721, etc.
My Goal:
To be able to punch in a particular GEO_id2 and search all four tables, returning only selected rows of data from those tables, and displaying them in a user-friendly format (e.g., instead of HC01 listed in the header, it should say “Median_family_income”). Additionally, the results should be listed in their appropriate format (e.g., 63.4 should display 63.4%, 47721 should display $47,721, etc.).
I have managed to do much of this using the following query:
/****** Script for SelectTopNRows command from SSMS ******/
SELECT
ACS_DP03.GEO_id2 AS FIPS,
ACS_DP03.HC01_VC114 AS Median_family_income,
ACS_DP02.HC03_VC11 AS Female_householder,
ACS_DP05.HC03_VC101 AS AmerIndian_Alaskan,
ACS_DP04.HC03_VC65 AS Owner_Occupied
FROM [Census].[dbo].[ACS_DP03]
INNER JOIN ACS_DP02 ON ACS_DP03.GEO_id2 = ACS_DP02.GEO_id2
INNER JOIN ACS_DP05 ON ACS_DP03.GEO_id2 = ACS_DP05.GEO_id2
INNER JOIN ACS_DP04 ON ACS_DP03.GEO_id2 = ACS_DP04.GEO_id2
WHERE ACS_DP03.GEO_id2 = 18097360405
AND ACS_DP02.GEO_id2 = 18097360405
AND ACS_DP05.GEO_id2 = 18097360405
AND ACS_DP04.GEO_id2 = 18097360405;
I can get the data to link up and display the right variables, but the formatting not exact. Also, as you can see from my SQL query, I would have to punch in the GEO_id2 multiple times.
Questions:
Is there a way I can shorten the WHERE & AND clauses to only punch in my GEO_id2 once?
How can I change the variables to their respective formats? (e.g., 47721 to $47,721, 22 to 22%, etc.) I thought I could combine ALIAS and CAST statements somehow, but I have not been successful in finding examples or trying it on my own.
For Question 1., only one where condition is enough for GEO_id2 because your tables are already joined with GEO_id2
For Question 2. you can use FORMAT. Ex:
FORMAT(ACS_DP03.HC01_VC114,'$#####') or
FORMAT(ACS_DP03.HC01_VC114, 'C', 'en-us') --> C stands for Currency
Reference

MS Access 2013, How to add totals row within SQL

I'm in need of some assistance. I have search and not found what I'm looking for. I have an assigment for school that requires me to use SQL. I have a query that pulls some colunms from two tables:
SELECT Course.CourseNo, Course.CrHrs, Sections.Yr, Sections.Term, Sections.Location
FROM Course
INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term="spring";
I need to add a Totals row at the bottom to count the CourseNo and Sum the CrHrs. It has to be done through SQL query design as I need to paste the code. I know it can be done with the datasheet view but she will not accept that. Any advice?
To accomplish this, you can union your query together with an aggregation query. Its not clear from your question which columns you are trying to get "Totals" from, but here's an example of what I mean using your query and getting counts of each (kind of useless example - but you should be able to apply to what you are doing):
SELECT
[Course].[CourseNo]
, [Course].[CrHrs]
, [Sections].[Yr]
, [Sections].[Term]
, [Sections].[Location]
FROM
[Course]
INNER JOIN [Sections] ON [Course].[CourseNo] = [Sections].[CourseNo]
WHERE [Sections].[Term] = [spring]
UNION ALL
SELECT
"TOTALS"
, SUM([Course].[CrHrs])
, count([Sections].[Yr])
, Count([Sections].[Term])
, Count([Sections].[Location])
FROM
[Course]
INNER JOIN [Sections] ON [Course].[CourseNo] = [Sections].[CourseNo]
WHERE [Sections].[Term] = “spring”
You can prepare your "total" query separately, and then output both query results together with "UNION".
It might look like:
SELECT Course.CourseNo, Course.CrHrs, Sections.Yr, Sections.Term, Sections.Location
FROM Course
INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term="spring"
UNION
SELECT "Total", SUM(Course.CrHrs), SUM(Sections.Yr), SUM(Sections.Term), SUM(Sections.Location)
FROM Course
INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term="spring";
Whilst you can certainly union the aggregated totals query to the end of your original query, in my opinion this would be really bad practice and would be undesirable for any real-world application.
Consider that the resulting query could no longer be used for any meaningful analysis of the data: if displayed in a datagrid, the user would not be able to sort the data without the totals row being interspersed amongst the rest of the data; the user could no longer use the built-in Totals option to perform their own aggregate operation, and the insertion of a row only identifiable by the term totals could even conflict with other data within the set.
Instead, I would suggest displaying the totals within an entirely separate form control, using a separate query such as the following (based on your own example):
SELECT Count(Course.CourseNo) as Courses, Sum(Course.CrHrs) as Hours
FROM Course INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term = "spring";
However, since CrHrs are fields within your Course table and not within your Sections table, the above may yield multiples of the desired result, with the number of hours multiplied by the number of corresponding records in the Sections table.
If this is the case, the following may be more suitable:
SELECT Count(Course.CourseNo) as Courses, Sum(Course.CrHrs) as Hours
FROM
Course INNER JOIN
(SELECT DISTINCT s.CourseNo FROM Sections s WHERE s.Term = "spring") q
ON Course.CourseNo = q.CourseNo

MS Access Query to output all values and treat unavailable values as zero

I've created a query MS Access 2010 that is intended to take all fuel types (all values) for each date. I have the query relationship below: ) and have the following 6 values for fuel type: Diesel #2, MSFO, ULSD, Biodiesel, Used Oil, Heat Recovery.
I'm trying to output the fuel delivery for each fuel type for each date regardless if there's any fuel delivered that date
and
. What I'm getting as my output is below
.
I have tried to change the relationships such that all values on tbl_FuelType would output. This gave me the output on the figure above. I've tried entering a criteria to look for the specific fuel type (e.g. "ULSD") but if there's no data for that day, it will output with Null values, which I don't want. See criteria below
I've tried some program flow functions such as IIF and Switch but still getting null values. Is there an easy way to do this without having to go into the table and filling out values as zero's for all the different fuel types on the tbl_FuelDelivery? The SQL view is as follows:
SELECT tbl_FuelDelivery.DateLog, Sum(Nz([tbl_FuelDelivery].[F_FO_gal_Gross],0)) AS Fuel_Delivery_Gross, Sum(Nz([tbl_FuelDelivery].[F_FO_gal_Net],0)) AS Fuel_Delivery_Net, tbl_FuelType.FuelType
FROM tbl_FuelType LEFT JOIN tbl_FuelDelivery ON tbl_FuelType.ID = tbl_FuelDelivery.FuelType
GROUP BY tbl_FuelDelivery.DateLog, tbl_FuelType.FuelType
ORDER BY tbl_FuelDelivery.DateLog;
​
What you need to add to your query is a table with all dates. You can have a separate table where all dates are entered, such a calendar table or have it derived from your tbl_FuelDelivery like this:
SELECT DISTINCT tbl_FuelDelivery.DateLog
FROM tbl_FuelDelivery;
Now, you need to CROSS JOIN this table with tbl_FuelType. Access does not natively support cross joins, so you'll have to use a workaround: just add the cross join as a comma separated table to your FROM clause:
SELECT a.DateLog, tbl_FuelType.FuelType, tbl_FuelType.ID
FROM (SELECT DISTINCT tbl_FuelDelivery.DateLog FROM tbl_FuelDelivery) a,
tbl_FuelType;
The query above will give you the all fuel types for all dates. You can save it as a new query (let's call it allDatesFuels). Now, all you need to do is to join it with your query:
SELECT
allDatesFuels.DateLog,
Sum(Nz([tbl_FuelDelivery].[F_FO_gal_Gross],0)) AS Fuel_Delivery_Gross,
Sum(Nz([tbl_FuelDelivery].[F_FO_gal_Net],0)) AS Fuel_Delivery_Net,
allDatesFuels.FuelType
FROM allDatesFuels LEFT JOIN tbl_FuelDelivery ON allDatesFuels.ID = tbl_FuelDelivery.FuelType And allDatesFuels.DateLog = tbl_FuelDelivery.DateLog
GROUP BY allDatesFuels.DateLog, allDatesFuels.FuelType
ORDER BY allDatesFuels.DateLog;
​

ORACLE SQL INQUIRY

I am using an oracle database I am buidling a query and am unsure how to do a compare with the field I set as 'Created'
SELECT C.IS_AW_TITLE, A.PORTAL_OBJNAME, C.IS_AW_ACTIVE_FLG,
(TO_CHAR(CAST((C.CREATEDTTM) AS TIMESTAMP),'YYYY-MM-DD-HH24.MI.SS.FF')) AS
CREATED,.....
FROM ..., (sysadm.PS_IS_AW_PG_DEFN C LEFT OUTER JOIN sysadm.PS_IS_AW_SECURITY D ON
C.IS_AW_GRP_ID = D.IS_AW_GRP_ID ),...
WHERE ( C.IS_AW_CREF_OBJ = A.PORTAL_OBJNAME
AND C.IS_AW_GRP_ID = E.IS_AW_GRP_ID...
the 'Created' field produces results similar to this example: 2011-09-26-11.22.31.000000
How would I include it in the query to say something like 'AND Created = to_timestamp(....., 2011-09-26-11.22.31.000000)?
You have let's say declared (not sure whether term is appropriate, feel free to correct me) created field as to_char, so its type is varchar2, that means you cannot compare it with to_timestamp.
I see several ways to do such comparsion:
Leave field as is, and compare CAST((C.CREATEDTTM) AS TIMESTAMP with the date you need;
Define created as timestamp, i.e. remove to_char;
Compare created with `to_char(to_timestamp(...));
Which one is the best fit would depend on how you're going to use created field in query result. If possible, personally I'd choose option 2.

Splitting text in SQL Server stored procedure

I'm working with a database, where one of the fields I extract is something like:
1-117 3-134 3-133
Each of these number sets represents a different set of data in another table. Taking 1-117 as an example, 1 = equipment ID, and 117 = equipment settings.
I have another table from which I need to extract data based on the previous field. It has two columns that split equipment ID and settings. Essentially, I need a way to go from the queried column 1-117 and run a query to extract data from another table where 1 and 117 are two separate corresponding columns.
So, is there anyway to split this number to run this query?
Also, how would I split those three numbers (1-117 3-134 3-133) into three different query sets?
The tricky part here is that this column can have any number of sets here (such as 1-117 3-133 or 1-117 3-134 3-133 2-131).
I'm creating these queries in a stored procedure as part of a larger document to display the extracted data.
Thanks for any help.
Since you didn't provide the DB vendor, here's two posts that answer this question for SQL Server and Oracle respectively...
T-SQL: Opposite to string concatenation - how to split string into multiple records
Splitting comma separated string in a PL/SQL stored proc
And if you're using some other DBMS, go search for "splitting text ". I can almost guarantee you're not the first one to ask, and there's answers for every DBMS flavor out there.
As you said the format is constant though, you could also do something simpler using a SUBSTRING function.
EDIT in response to OP comment...
Since you're using SQL Server, and you said that these values are always in a consistent format, you can do something as simple as using SUBSTRING to get each part of the value and assign them to T-SQL variables, where you can then use them to do whatever you want, like using them in the predicate of a query.
Assuming that what you said is true about the format always being #-### (exactly 1 digit, a dash, and 3 digits) this is fairly easy.
WITH EquipmentSettings AS (
SELECT
S.*,
Convert(int, Substring(S.AwfulMultivalue, V.Value * 6 - 5, 1) EquipmentID,
Convert(int, Substring(S.AwfulMultivalue, V.Value * 6 - 3, 3) Settings
FROM
SourceTable S
INNER JOIN master.dbo.spt_values V
ON V.Value BETWEEN 1 AND Len(S.AwfulMultivalue) / 6
WHERE
V.type = 'P'
)
SELECT
E.Whatever,
D.Whatever
FROM
EquipmentSettings E
INNER JOIN DestinationTable D
ON E.EquipmentID = D.EquipmentID
AND E.Settings = D.Settings
In SQL Server 2005+ this query will support 1365 values in the string.
If the length of the digits can vary, then it's a little harder. Let me know.
Incase if the sets does not increase by more than 4 then you can use Parsename to retrieve the result
Declare #Num varchar(20)
Set #Num='1-117 3-134 3-133'
select parsename(replace (#Num,' ','.'),3)
Result :- 1-117
Now again use parsename on the same resultset
Select parsename(replace(parsename(replace (#Num,' ','.'),3),'-','.'),1)
Result :- 117
If the there are more than 4 values then use split functions