In the below table structure, TB_Vehicles is the Master table and TB_Cars, TB_Bikes, TB_Cars are Satellite tables which hold more info about respective vehicles.
**TB_Scooters**
V_NAME V_ID V_YEAR V_TYPE V_MILEAGE
Activa 10 2003 Scooter 45
Access 20 2004 Scooter 50
**TB_Bikes**
V_NAME V_ID V_YEAR V_TYPE V_ENGINE
Karizma 30 2001 Bike 180
Pulsar 40 2008 Bike 150
**TB_Cars**
V_NAME V_ID V_YEAR V_TYPE V_CAR_TYPE
Linea 50 2011 Car Sedan
i20 60 2012 Car Sedan
**TB_Vehicles**
V_NAME V_ID V_YEAR V_TYPE V_COLOR V_AVAILABLE
Activa 10 2003 Scooter Black Yes
Access 20 2004 Scooter Black No
Karizma 30 2001 Bike Red Yes
Pulsar 40 2008 Bike Black Yes
Linea 50 2011 Car White No
i20 60 2012 Car Red Yes
I want users to search using the Name. So, when users enter Name as 'Access', my query should give all information about that vehicle, including that from Satellite Tables (using both TB_Vehicles and TB_Scooters).
SELECT * FROM TB_Vehicles
WHERE V_NAME = 'Access';
Similarly, if user enters 'Linea', it should give info from TB_Vehicles and TB_Cars tables.
So, with V_NAME as input, I'll find V_TYPE from TB_Vehicles table, and using that, I need to identify which satellite table, I need to join to retrieve more info.
How do I do this? Can you please help me with the query? Do I need to use CASE or DECODE to achieve this?
EDIT:
The requirement here is to display only those columns which are applicable for that particular vehicle type. So, when user gives 'Access' as input, it should display all columns from TB_Vehicles table, and V_MILEAGE from TB_Scooters table.
I was thinking whether this can be done using CASE or DECODE, where I first identify the type (V_TYPE) of the vehicle from TB_Vehicles table using the input name (V_NAME), and then based on this V_TYPE, I'll search the relevant table and display only relevant columns.
When Input Name is 'Access', then result should be:
V_NAME V_ID V_YEAR V_TYPE V_COLOR V_AVAILABLE V_MILEAGE
Access 20 2004 Scooter Black No 50
When Input Name is 'i20', then result should be:
V_NAME V_ID V_YEAR V_TYPE V_COLOR V_AVAILABLE V_CAR_TYPE
i20 60 2012 Car Red Yes Sedan
You shouldn't be storing the name in both the vehicles tables and the subtables. If this is common information, then just store it in the vehicles table. This is true of all the common columns.
Next, when you access data, do it by bringing together all the tables:
select v.*,
s.v_mileage, b.v_engine, c.v_car_type
from TB_vehicles v left join
TB_Scooters s
on s.v_id = v.v_id and v.type = 'scooter' left join
TB_Bikes b
on b.v_id = v.v_id and v.type = 'bike' left join
TB_Cars c
on c.v_id = v.vid and v.type = 'car';
From this query, you can then choose the row and the fields that you want.
However, you need to work on normalizing your data structure so fields like v_year are only in one table.
Thanks Gordon! Appreciate your help over this...
For others with similar query, please look into the above response from Gordon as well as the below link:
http://www.orafaq.com/forum/t/189451/180198/
Related
I work with QGIS and PostgreSQL with PostGIS. I need help with dynamic queries for PostgreSQL.
Information is structured in tables that contain votes for parties, and other types of information like geographic area or election date.
I need to work with “tidy” data in plotly for pie charts. The desired end table must have one row per observation.
So for example for the given table “Election Results”:
Country
PartyA
PartyB
PartyC
Argentina
100
10
20
Uruguay
3
5
1
Chile
40
200
50
Values for columns to be treated like parties, are stored in table “Parties”:
Party
PartyA
PartyB
PartyC
PartyD
PartyE
I need to separate one observation of voting results per row as follows (“Ending Table”):
Country
Party
Votes
Argentina
PartyA
100
Argentina
PartyB
10
Argentina
PartyC
20
Uruguay
PartyA
3
Uruguay
PartyB
5
Uruguay
PartyC
1
Chile
PartyA
40
Chile
PartyB
200
Chile
PartyC
50
The query should work with any number of parties stored in the “Parties” table. The “parties” table could include some rows not present in the election results table, but all parties in the election results table will exist in the “parties” table.
I understand it should be done iterating over the columns in the “Election results” table. If the name of a column matches the value of a row in “party table”, then we “untidy” data as in the “ending table”.
You can "iterate" over the columns using Postgres's JSON functions:
Something like this:
select er."Country",
pv.*
from election_results er
cross join jsonb_each_text(to_jsonb(er) - 'Country') as pv(party, votes)
join parties p on p.party = pv.party
;
Online example
I've been using Databasedevelopment.co.uk's excellent example on how to do a continuous form select with a invisible button overlaying a checkbox to assign employees to a specific shift. I'd like to make it so that said continuous form also has a dropdown of the different Paycodes so that when they are selected I can use a combobox to indicate "Regular Pay, Overtime, etc....". I'm running into a wall because with the query as-is from the example, the recordset for the Paycode field is not updateable.
Messing with the primary key for the employee's table fixes the paycode issue but prevents the selection code from working properly.
I'm a bit out of my depth here, what's the easiest way to accomplish this?
SELECT CAT.EmployeeID, CAT.FirstName, CAT.LastName, ASGN_TEMP.ShiftNum, ASGN.PayCode, IIf(ASGN_TEMP.[ShiftNum] Is Null,0,-1) AS IsSelected
FROM tblEmployees AS CAT
LEFT JOIN (SELECT ASGN.EmployeeID, ASGN.ShiftNum, ASGN.PayCode FROM tblAssignedEmployees AS ASGN
WHERE ASGN.ShiftNum = Forms!frmMainMenu![txtShiftNum]) AS ASGN_TEMP
ON CAT.EmployeeID = ASGN_TEMP.EmployeeID;
Paycode is a static table with an ID, a Paycode and a description and would only correspond with each record in "tblAssignedEmployee". That is to say, there is no relationship between the employee or the shift with what Paycodes are available, I'd just like a second table for ease of updates.
---EDIT---
Table: Employees
ID
EmployeeID
Firstname
LastName
1
1234
Bob
Jones
2
9999
Mary
Sue
Table: AssignedEmployees
ID
EmployeeID
ShiftNum
PayCode
1
1234
1
OT
2
9999
2
Regular
3
1234
2
OT
Table: PayCodes
ID
PayCode
Desc
1
Regular
Regular Pay
2
OT
Overtime
The other day I asked how to generate a list of currencies based on a built-in oracle table if possible: Does oracle provide a built-in currency table for me to use as constraints?.
Now I need a list of the language codes, so I went to read the documentation for util_i18n and I found a function named GET_LOCAL_LANGUAGES. I tried to adapt the script from the previous answer to this new problem but failed. This is mainly because my oracle/sql knowlegde is terrible:
The original I'm trying to adapt from:
select utl_i18n.GET_DEFAULT_ISO_CURRENCY(value) iso_cur
from v$nls_valid_values
where parameter = 'TERRITORY'
My attempt to use it for the languages:
select utl_i18n.GET_LOCAL_LANGUAGES(value) lang_cur
from v$nls_valid_values
where parameter = 'TERRITORY'
I checked the docs and TERRITORY is the parameter name as well, that part was not a guess. With this query I get error: invalid data type
I bet this is a noob question, but all my tries have failed so far.
You can use pipelined wrapper for example (original function returns package-defined collection type):
SQL> create type t_lang_tab is table of varchar2(4000)
2 /
SQL> create or replace function get_language(
2 p_value in varchar2
3 ) return t_lang_tab
4 pipelined
5 is
6 res utl_i18n.string_array;
7 begin
8 res := utl_i18n.GET_LOCAL_LANGUAGES(p_value);
9 if res is not null then
10 for i in 1..res.count loop
11 pipe row (substr(res(i),1,4000));
12 end loop;
13 end if;
14 return;
15 end;
16 /
SQL> col column_value format a25
SQL> col value format a25
SQL> select t.column_value, p.value
2 from v$nls_valid_values p,
3 table(get_language(p.value)) t
4 where parameter = 'TERRITORY'
5 /
COLUMN_VALUE VALUE
------------------------- -------------------------
ENGLISH AMERICA
GERMAN DIN GERMANY
CANADIAN FRENCH CANADA
FRENCH CANADA
CATALAN SPAIN
SWEDISH FINLAND
PORTUGUESE BRAZIL
LATIN AMERICAN SPANISH MEXICO
SPANISH MEXICO
SPANISH CATALONIA
ARABIC EGYPT
....
If you want to create language table you can do this:
SQL> CREATE TABLE languages (
2 country VARCHAR2(30) NOT NULL,
3 language VARCHAR2(30) NOT NULL,
4 CONSTRAINT languages_pk PRIMARY KEY (country, language)
5 )
6 /
Primary key should be composite because there are multi-lingual countries like Canada.
Now you can use above function to fill table:
SQL> INSERT INTO languages
2 select p.value, t.column_value
3 from v$nls_valid_values p,
4 table(get_language(p.value)) t
5 where parameter = 'TERRITORY'
6 order by 1
7 /
SQL> commit;
SQL> select * from languages;
COUNTRY LANGUAGE
------------------------------ ------------------------------
AMERICA ENGLISH
ARGENTINA SPANISH
BELARUS RUSSIAN
BELGIUM FRENCH
BRAZIL PORTUGUESE
CANADA FRENCH
CANADA CANADIAN FRENCH
CATALONIA SPANISH
CHILE SPANISH
COLOMBIA SPANISH
...
I have a table like this:
StudentID Student Name Birthdate Student Birthplace Gender Height Weight
--------- --------------- --------- ------------------ ------ ------ ------
83 Adam Stone 30-JUN-94 Towson, USA M 193 88
84 Stephanie Love 17-JUN-93 KL,Malaysia F 176 67
85 Rachel Kim 17-FEB-92 Seoul, South Korea F 179 56
How do i write a trigger to prevent any student under the age of 15 from being stored in the student's table?
You have a Date of Birth. So you need to determine that the DoB is at least sixteen years before today. There are various different ways of doing this; here's one using an interval literal.
create or replace trigger students_biur
before insert or update on students for each row
begin
if (:new.student_birthdate + INTERVAL '15' YEAR ) < sysdate
then
raise_application_error( -20000, 'This student is too young be registered.');
end if;
end;
This trigger also checks for updates, to prevent subsequent changes invalidating an student.
The trigger name students_biur is just a convention I use: the table name with a suffix indicating *B*efore *I*nsert *U*pdate for each *R*ow.
RAISE_APPLICATION_ERROR is a standard procedure for throwing user-defined exceptions with a message. Find out more.
Oracle reserves the range -20999 to -20000 for user-defined errors; any other number may clash with a oracle-defined exception.
I have a large table with sales data, useful data below:
RowID Date Customer Salesperson Product_Type Manufacturer Quantity Value
1 01-06-2004 James Ian Taps Tap Ltd 200 £850
2 02-06-2004 Apple Fran Hats Hats Inc 30 £350
3 04-06-2004 James Lawrence Pencils ABC Ltd 2000 £980
...
Many rows later...
...
185352 03-09-2012 Apple Ian Washers Tap Ltd 600 £80
I need to calculate a large set of targets from table containing values different types, target table is under my control and so far is like:
TargetID Year Month Salesperson Target_Type Quantity
1 2012 7 Ian 1 6000
2 2012 8 James 2 2000
3 2012 9 Ian 2 6500
At present I am working out target types using a view of the first table which has a lot of extra columns:
SELECT YEAR(Date)
, MONTH(Date)
, Salesperson
, Quantity
, CASE WHEN Manufacturer IN ('Tap Ltd','Hats Inc') AND Product_Type = 'Hats' THEN True ELSE False END AS IsType1
, CASE WHEN Manufacturer = 'Hats Inc' AND Product_Type IN ('Hats','Coats') THEN True ELSE False END AS IsType2
...
...
, CASE WHEN Manufacturer IN ('Tap Ltd','Hats Inc') AND Product_Type = 'Hats' THEN True ELSE False END AS IsType24
, CASE WHEN Manufacturer IN ('Tap Ltd','Hats Inc') AND Product_Type = 'Hats' THEN True ELSE False END AS IsType25
FROM SalesTable
WHERE [some stuff here]
This is horrible to read/debug and I hate it!!
I've tried a few different ways of simplifying this but have been unable to get it to work.
The closest I have come is to have a third table holding the definition of the types with the values for each field and the type number, this can be joined to the tables to give me the full values but I can't work out a way to cope with multiple values for each field.
Finally the question:
Is there a standard way this can be done or an easier/neater method other than one column for each type of target?
I know this is a complex problem so if anything is unclear please let me know.
Edit - What I need to get:
At the very end of the process I need to have targets displayed with actual sales:
Type Year Month Salesperson TargetQty ActualQty
2 2012 8 James 2000 2809
2 2012 9 Ian 6500 6251
Each row of the sales table could potentially satisfy 8 of the types.
Some more points:
I have 5 different columns that need to be defined against the targets (or set to NULL to include any value)
I have between 30 and 40 different types that need to be defined, several of the columns could contain as many as 10 different values
For point 2, if I am using a row for each permutation of values, 2 columns with 10 values each would give me 100 rows for each sales person for each month which is a lot but if this is the only way to define multiple values I will have to do this.
Sorry if this makes no sense!
If I am correct that the "Target_Type" field in the Target Table is based on the Manufacturer and the Product_Type, then you can create a TargetType table that looks like what's below and JOIN on Manufacturer and the Product_Type to get your Target_Type_Value:
ID Product_Type Manufacturer Target_Type_Value
1 Taps Tap Ltd 1
2 Hats Hats Inc 2
3 Coats Hats Inc 2
4 Hats Caps Inc 3
5 Pencils ABC Ltd 6
This should address the "multiple values for each field" problem by having a row for each possibility.