I have some parent and daughter design-wise locations-id in the MySQL database.
Where the daughter linked to the parent. I will show the database design below -
I can able to fetch the data when I search it through daughter location id wise but I don't have any idea how I combined the daughter value when I click parent location.
For example -
MainLocation (123) //total stock 23+10+56= 89
|
|
|---- DaughterLoc1 (456) //suppose stock 23
|
|---- DaughterLoc2 (789) //suppose stock 10 and total stock 10+56 = 66
|
|
|---DaughterLocA (963) //suppose stock 56
SQL : SELECT stock FROM table WHERE location = '456'
OUTPUT = 23 (Corrent)
But I want when searching location 123 I want output 89
My table design is like this below -
table: LocParent
-------------------------
| ID | stock | loc_id |
-------------------------
| 1 | 10 | 789 |
-------------------------
`location`
--------------------------------------------------------------------------------
| ID | main_loc | main_loc_id | loc_under | loc_under_id | stock |
--------------------------------------------------------------------------------
| 1 | MainLocation | 123 | DaughterLoc1 | 456 | 23 |
--------------------------------------------------------------------------------
| 2 | MainLocation | 123 | DaughterLoc2 | 789 | 10 |
--------------------------------------------------------------------------------
It is hard to tell from your sample structure what things actually look like still, and it is further complicated by multiple things called an "id". But, generally speaking, if your depth is finite, you can make small sub-queries, and if your depth is infinite (or unbound) you can make a recursive query.
Here is a sample database. It doesn't match yours, but hopefully it make sense still. If it doesn't, it would help if you provided an actual schema and data (excluding irrelevant columns).
This table is self-referencing to make things easier for demo.
CREATE TABLE sample
(
id int AUTO_INCREMENT NOT NULL,
parent_id INT NULL,
stock int NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT FOREIGN KEY (`parent_id`) REFERENCES `sample` (`id`)
);
And here's some sample data. There are two records that are "root" and don't have parent values (IDs 1 and 5), two child values (IDs 2 and 3) and one grandchild value (ID 4)
INSERT INTO sample VALUES (1, null, 11);
INSERT INTO sample VALUES (2, 1, 22);
INSERT INTO sample VALUES (3, 1, 33);
INSERT INTO sample VALUES (4, 2, 4);
INSERT INTO sample VALUES (5, null, 55);
Finite/bound
If you have a finite/bound depth, you can make use of subqueries like the below. This one goes to a depth of 3 and sums to 70. Hopefully it is fairly easy to read, but I've included a couple of comments.
SELECT
s.id,
s.stock -- root
+
(
(
SELECT
SUM(c.stock) -- child
FROM
sample c
WHERE
c.parent_id = s.id
)
+
(
SELECT
SUM(p.stock) -- grandchild
FROM
sample c
JOIN
sample p
ON
p.parent_id = c.id
WHERE
c.parent_id = s.id
)
)
as three_level_sum
FROM
sample s
WHERE
s.id = 1;
Infinite/unbound
If you have an infinite hierarchy, however, things get more complicated. MySQL and other database platforms have a thing called "Common Table Expressions" (CTEs) that allow you to make recursive queries. These can be harder to wrap your head around because of the recursion, but it basically does the same as the previous version, just with infinite depth. This version also returns the sum of 70.
WITH RECURSIVE sample_rec AS
(
SELECT
id AS root_id,
id,
parent_id,
stock
FROM
sample
WHERE
parent_id IS NULL
UNION ALL
SELECT
R.root_id,
E.id,
E.parent_id,
E.stock
FROM
sample E
INNER JOIN
sample_rec R
ON
E.parent_id = R.id
)
SELECT
SUM(stock)
FROM
sample_rec
WHERE
root_id = 1
Related
I have a mySQL table that holds n number of pictures.
+------------+--------------+
| picture_id | picture_name |
+------------+--------------+
| 1 | ben.jpg |
| 2 | nick.jpg |
| 3 | mark.jpg |
| 4 | james.jpg |
| .. | ... |
| n | abraham.jpg |
+------------+--------------+
For a web application, i need to display 2 pictures simultaneously where the user can vote for one picture or the other. After voting, the user gets a new set of two pictures.
(application use interface)
+---------------------+--------------------+
| Vorte for picture 1 | Vote for picture 2 |
+---------------------+--------------------+
I would like to avoid displaying the same combinations as much as possible. I can create a helper table that will hold all possible combinations.
+----------------+--------------+--------------+
| combination_id | picture_id_1 | Picture_id_2 |
+----------------+--------------+--------------+
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 4 |
| 4 | 1 | 5 |
| .. | .. | .. |
| (n^2-n)/2 | .. | .. |
+----------------+--------------+--------------+
but for 100 pictures, that would be (100^2 - 100)/2 = 4950 (edit) rows, and with every added picture the table would grow exponentially. (which is not a big issue in todays computing i suppose)
But how do i query this table in a way that the user always sees as little duplicates as possible.
Expected result:
run 1: picture_id's = 4,5 (any numbers between 1 and n)
run 2: picture_id's = 2,7
run 3: picture_id's = 5 and 20
...
DEMO:http://rextester.com/VNWIOA4679 (added 100 pic samples) 2 sec query for 1 user w/o any indexes.
I see no need for a helper table as the data can easily be constructed on the fly with proper indexes. at 1000 pictures you're looking at 499,500 combinations a user could vote upon. still easily managed within a database construct as we operate on a set level, not a record level.
Here's one way assuming my own table structures. I can't think of a more efficient way to store/process the data.
Using this approach as new pictures are added the query will generate a larger and larger combination set but always exclude those on which a user has already voted. no code changes for new pics, no regenerating sets just processing each time the ones a user hasn't made a selection upon.
Create table SO46205797_Pics(
PICID int);
Insert into SO46205797_Pics values (1);
Insert into SO46205797_Pics values (2);
Insert into SO46205797_Pics values (3);
Insert into SO46205797_Pics values (4);
Insert into SO46205797_Pics values (5);
Insert into SO46205797_Pics values (6);
Insert into SO46205797_Pics values (7);
Create table SO46205797_UserPicResults (
USERID int,
PICID int,
PICID2 int,
PICChoiceID int);
Insert into SO46205797_UserPicResults values (1,1,2,1);
Insert into SO46205797_UserPicResults values (1,1,3,1);
Insert into SO46205797_UserPicResults values (1,1,4,4);
magic happens here the above was just data setup.
SELECT A.PICID, B.PICID, C.PICChoiceID
FROM SO46205797_Pics A
INNER JOIN SO46205797_Pics B
on A.PICID < B.PICID
LEFT JOIN SO46205797_UserPicResults C
on A.PICID = C.PicID
and B.PICID = C.PICID2
and C.USERID = 1
WHERE C.userID is null;
Note that if we eliminate the C.userID is null part then we see all of the possible combinations (for user1) (note I treat ID 1, 2 the same as ID 2,1 which I think youw ant) for the 2 photos and which ones the user has selected. Since we don't want to display that choice again, we use the c.userID is null to exclude combinations the user already made a choice for.
Also when saving data to the userPicResults, you need to ensure PICID1 is always less than PICID2.
A different way to do this is using a not exists which may be slightly faster.
obviously indexes on USERID, PICID, PICID2 and in that order would be beneficial (i'd probably make it the a combined PK) for SO46205797_UserPicResults and an index on PICID for SO46205797_Pics as the PK.
SELECT A.PICID, B.PICID
FROM SO46205797_Pics A
INNER JOIN SO46205797_Pics B
on A.PICID < B.PICID
WHERE not exists (SELECT *
FROM SO46205797_UserPicResults C
WHERE A.PICID = C.PicID
and B.PICID = C.PICID2
and C.USERID = 1);
I considered maintaining a parent/child relationship for each image for each user; but this approach doesn't store the choices for all combinations.
The goal of this application is to let people vote for one picture against another, right? Then you need to have some kind of vote results table:
vote_results:
| vote_id | user_id | vote_up_picture_id | vote_down_picture_id | ...
Then, based on data from this table you can easily show to a user picture pairs, which he haven't seen yet:
select first.picture_id, second.picture_id
from pictures as first, pictures as second
where not exists(
select * from vote_results v
where (v.vote_up_picture_id = first.picture_id and v.vote_down_picture_id = second.picture_id)
or (v.vote_up_picture_id = second.picture_id and v.vote_down_picture_id = first.picture_id)
) and first.picture_id != second.picture_id
order by rand()
limit 1
PS. As you see, there is no need in helper table with combination_id
My head is already spinning from this and I need your help.
MY DATABASE
imported CSV file: 22 columns and 11k rows
2 tables with the same data (both created from the CSV)
Added ID as PRIMARY KEY to both
All VARCHAR(60) Some columns are empty strings ' '
DB:
PID | CODE 1 | CODE 2 | CODE 3 | CODE 4 | CODE 5 | CODE X (up to 9) | ID
-------------------------------------------------------------------------
1 | a | b | c | | | | 1
2 | a | | b | d | | | 2
3 | x | | | | | y | 3
DB has 22 columns but I'm only including CODE columns (up to 9)
in which I might be interested in terms of SQL statement.
It'll be only read table - MyISAM engine then?
WHAT I'D LIKE TO DO
select PID = 1 from first table
and retrieve all PIDs from second table
IF
selected PID's column CODE 1
or
selected PID's column CODE 2 (which is b) etc (up to 9).
= any PID's CODE X
So I should get only PID 2.
edit: PID is not a ID, it's just an example code, it could be string: '002451' and I'm looking for other PIDs with the same CODES (e.g PID1 has code = a so it should find PID2 becasue one of its CODE columns contains a)
MY ATTEMPT
SELECT a.* FROM `TABLE1` a WHERE
(
SELECT * FROM `TABLE2` b WHERE b.`PID` = 1
AND
(
( b.`CODE 1` NOT IN ('') AND IN (a.`CODE 1`,a.`CODE 2`, A.`CODE 3`...) ) OR
( b.`CODE 2` NOT IN ('') AND (a.`CODE 1`,a.`CODE 2`, A.`CODE 3`...) ) OR...
I'd end up with large query - over 81 conditions. In terms of performance... well, it doesn't work.
I intuitively know that I should:
use INDEXES (on CODE 1 / CODE 2 / CODE 3 etc.?)
use JOIN ON (but I'm too stupid) - that's why I created 2 tables (let's assume I don't want TEMP. TABLES)
How to write the SQL / design the DB efficently?
The correct data structure is one row per pid and code. The simplest way is:
create table PCodes (
pid int not null,
code varchar(255),
constraint fk_PCodes_pid references p(pid)
);
Then you have the values in a single column and it is much simpler to check for matching codes.
In practice, you should have three tables:
create table Codes (
CodeId int not null auto_increment primary key,
Code varchar(255)
);
create table PCodes (
pid int not null,
codeid int not null,
constraint fk_PCodes_pid references p(pid),
constraint fk_PCodes_codeid references codes(codeid);
);
If the ordering of the codes is important for each "p", then include a priority or ordering column in the PCodes table.
I want to get the greatest (or lowest) value in a field for a specific value of a different field but I am a bit lost. I am already aware of answered questions on the topic, but I already have a join in my query and I can't apply the terrific answers I found on my specific problem.
I have two tables, namely register and records. Records has all (weather) stations listed once for each month (each stationid represented 12 times, if complete data exists, a stationid can thus not be presented more than 12 times), and register has all stations listed with some of their characteristics. For the sake of the example, the two tables look pretty much like this:
CREATE TABLE IF NOT EXISTS `records` (
`stationid` varchar(30),
`month` int(11),
`tmin` decimal(3,1),
`tmax` decimal(3,1),
`commentsmax` text,
`commentsmin` text,
UNIQUE KEY `webcode` (`stationid`,`month`)
);
INSERT INTO `records` (`stationid`, `month`, `tmin`, `tmax`, `commentsmin`, `commentsmax`) VALUES
('station1', 7, '10.0', '46.0', 'Extremely low temperature.', 'Very high temperature.'),
('station2', 7, '15.0', '48.0', 'Very low temperature.', 'Extremely low temperature.'),
('station1', 1, '-10', '15', 'Extremely low temperature.', 'Somewhat high temperature.');
CREATE TABLE IF NOT EXISTS `register` (
`stationid` varchar(30),
`stationname` varchar(40),
`stationowner` varchar(10),
`georegion` varchar(40),
`altitude` int(4),
KEY `stationid` (`stationid`)
);
INSERT INTO `register` (`stationid`, `stationname`, `stationowner`, `georegion`, `altitude`) VALUES
('station1', 'Halifax', 'Maria', 'the North', 16),
('station2', 'Leeds', 'Peter', 'the South', 240);
The desired output is:
+-------------+-------+-------+---------------+-----------+----------+-----------------------------+
| stationname | month | tmin | stationowner | georegion | altitude | commentsmin |
+-------------+-------+-------+---------------+-----------+----------+-----------------------------+
| Leeds | 7 | 15.0 | Peter | the South | 240 | Very low temperature |
| Halifax | 1 | -10.0 | Maria | the North | 16 | Extremely low temperature |
+-------------+-------+-------+---------------+-----------+----------+-----------------------------+
where each station appears only one with the lowest temperatures from table 'records', including some station properties from the table 'register'. I am using the following code:
SELECT register.stationname, records.month, min(records.tmin), register.stationowner, register.georegion, register.altitude, records.commentsmin FROM records INNER JOIN register ON records.stationid=register.stationid GROUP BY records.stationid ORDER BY min(tmin) ASC
but it doesn't give the correct bits of the records table corresponding to the lowest tmin values BY stationid when there are many records in the tables.
I have seen solutions like this one here: MySQL Greatest N Results with Join Tables, but I just can't get my head around applying it on my two tables. I would be grateful for any ideas!
SELECT stuff
FROM some_table x
JOIN some_other_table y
ON y.something = x.something
JOIN
( SELECT something
, MIN(something_other_thing) min_a
FROM that_other_table
GROUP
BY something
) z
ON z.something = y.something
AND z.min_a = y.another_thing;
I asked this question previously, then someone suggested that it was a duplicate of another previously answered question. However, I could not adapt that solution to what I need despite 3 hours of trying.
So, my new question is how to adapt that solution to my own needs.
A simplified version of my category/subcategory database schema looks like this:
tblAllCategories
record_id title level parent_cat_id parent_id keywords
-------------------------------------------------------------------------------------------
1 Antiques & Collectables 0 NULL NULL junk
2 Art 0 NULL NULL
25 Furniture 1 1 1
59 Office Furniture 2 1 25 retro,shabby chic
101 Chairs 3 1 59
Notes:
Level 0 = top-level category, level 1 = second level, etc
parent_cat_id is the top-level category (i.e. having level 0)
parent_id refers to the level immediately above the relevant level
I added the keyword column to assist keyword searches so that items in certain relevant categories would be returned if the user entered a keyword but did not select a category to drill down into.
So, at the front end, after the user enters keyword, e.g., "Retro", I need to return not only the category that has the term "retro" in its keyword column, but also all higher level categories. So, according to the schema above, a search on "retro" would return category 59 along with its super-categories - 25 and 1.
The query should be sorted by level, such that the front end search results would look something like this (after necessary coding):
The solution offered is from this question
And the query is as follows:
SELECT T2.id, T2.title,T2.controller,T2.method,T2.url
FROM (
SELECT
#r AS _id,
(SELECT #r := parent_id FROM menu WHERE id = _id) AS parent_id,
#l := #l + 1 AS lvl
FROM
(SELECT #r := 31, #l := 0) vars,
menu m
WHERE #r <> 0) T1
JOIN menu T2
ON T1._id = T2.id
ORDER BY T1.lvl DESC;
I need to adapt this query to work off a passed keyword, not an ID.
Edit the vars subquery to have #r equal to the record_id of the row with the keywork, something like
SELECT T2.record_id, T2.title,T2.level,T2.keywords
FROM (SELECT #r AS _id
, (SELECT #r := parent_id
FROM tblAllCategories
WHERE record_id = _id) AS parent_id
, #l := #l + 1 AS lvl
FROM (SELECT #r := record_id, #l := 0
FROM tblAllCategories
WHERE keywords like '%retro%') vars
, tblAllCategories m
WHERE #r <> 0) T1
JOIN tblAllCategories T2 ON T1._id = T2.record_id
ORDER BY T1.lvl DESC;
SQLFiddle demo
Having the keywork as a comma separated values is not the best, a many to many relationship between this table and a keyword table (with the compulsory junction table) will be better as it will avoid the use of LIKE. In this example if there were another category with the keyword 'retrobike' that category and all his hierarchy will also be in the result.
This is going to take a while so get some coffee.
There are a lot of good resources available for hierarchical development. Most of what you will see below comes from sites like this and it refers you to Celko which I hardily recommend.
The first thing you'll have to do is remove the keywords field. The extra effort in development, use and maintenance is nowhere near the benefit received. I'll show you how to implement it later.
In this design, think of a row as a node. Each node has two values, the left boundary and the right boundary. These form a range or span of influence. If a node has boundaries of 1:4 and another node has 2:3, the second node is a subnode of the first as its span is contained in the span of the first. Also, as the boundaries of the second node are consecutive, there can be no node below it, so it must be a leaf node. This may sound complicated at first, especially when considering many levels of nodes, but you will see how the SQL is relatively easy to write and the maintenance effort for the table is minimal.
The complete script is here.
CREATE TABLE categories (
id INT not null auto_increment PRIMARY KEY,
name VARCHAR( 50 ) NOT NULL,
lBound INT NOT NULL,
rBound INT NOT NULL,
-- MySQL does not implement check constraints. These are here for illustration.
-- The functionality will be implemented via trigger.
CONSTRAINT cat_ptr_incr_chk CHECK ( lBound < rBound ), -- basic integrity check
CONSTRAINT cat_ptr_root_chk CHECK ( lBound >= 0 ) -- eliminates negative values
);
create unique index ndx_cat_lBound on categories( lBound );
create unique index ndx_cat_rBound on categories( rBound );
Notice there is nothing here that say "I'm a leaf node", "I'm a root" or "My root node is such-and-such." This information is all encompassed by the lBound and rBound (left boundary, right boundary) values. Let's build a few nodes so we can see what this looks like.
INSERT INTO categories( name, lBound, rBound )
values( 'Categories', 0, 1 );
ID name lBound rBound
== ========== ====== ======
1 Categories 0 1
This we do before creating the triggers on the table. That's really so the insert trigger doesn't have to have special code that must recognize when the first row (the root node of the entire structure). That code would only be executed when the first row is inserted and never again. Now we don't have to worry about it.
So now me have the root of the structure. Notice that its bounds are 0 and 1. Nothing can fit between 0 and 1 so this is a leaf node. The tree root is also a leaf. That means the tree is empty.
So now we write the triggers and dml procedures. The code is in the script so I won't duplicate it here, just say that the insert and delete triggers will not allow just anyone to issue an Insert or Delete statement. Anyone may issue an Update, but only the name is allowed to be changed. The only way Inserts, Deletes and complete Updates may be performed is through the procedures. With that in mind, let's create the first node under the root.
call ins_category( 'Electronics', 1 );
This creates a node with the name 'Electronics' as a subnode of the node with ID=1 (the root).
ID name lBound rBound
== ========== ====== ======
1 Categories 0 3
2 Electronics 1 2
Notice how the trigger has expanded the right boundary of the root to allow for the new node. The next node will be yet another level.
call ins_category( 'Televisions', 2 );
Node 2 is Electronics so the new node will be its subnode.
ID name lBound rBound
== ========== ====== ======
1 Categories 0 5
2 Electronics 1 4
3 Televisions 2 3
Let's create a new upper level node -- still it must be under the root, but will be the start of a subtree beside Electronics.
call ins_category( 'Antiques & Collectibles', 1 );
ID name lBound rBound
== ========== ====== ======
1 Categories 0 7
2 Electronics 1 4
3 Televisions 2 3
4 Antiques & Collectibles 5 6
Notice the 5-6 does not fit between any boundary range except for the root. So it is a subnode directly under the root, just like Electronics, but is independent of the other subnodes.
The SQL to give a clearer picture of the structure is not complicated. After completing the tree with a lot more nodes, let's see what it looks like:
-- Examine the tree or subtree using pre-order traversal. We start at the node
-- specified in the where clause. The root of the entire tree has lBound = 0.
-- Any other ID will show just the subtree starting at that node.
SELECT n.ID, n.NAME, n.lBound, n.rBound
FROM categories p
join categories n
on n.lBound BETWEEN p.lBound AND p.rBound
where p.lBound = 0
ORDER BY n.lBound;
+----+----------------------------+--------+--------+
| id | name | lBound | rBound |
+----+----------------------------+--------+--------+
| 1 | >Categories | 0 | 31 |
| 2 | -->Electronics | 1 | 20 |
| 3 | ---->Televisions | 2 | 9 |
| 4 | ------>Tube | 3 | 4 |
| 5 | ------>LCD | 5 | 6 |
| 6 | ------>Plasma | 7 | 8 |
| 7 | ---->Portable Electronics | 10 | 19 |
| 8 | ------>MP3 Players | 11 | 14 |
| 9 | -------->Flash | 12 | 13 |
| 10 | ------>CD Players | 15 | 16 |
| 11 | ------>2-Way Radios | 17 | 18 |
| 12 | -->Antiques & Collectibles | 21 | 28 |
| 14 | ---->Furniture | 22 | 27 |
| 15 | ------>Office Furniture | 23 | 26 |
| 16 | -------->Chairs | 24 | 25 |
| 13 | -->Art | 29 | 30 |
+----+----------------------------+--------+--------+
The output above is actually from a view defined in the script, but it shows clearly the hierarchical structure. This may easily be converted to a set of nested menus or navigational nodes.
There are enhancements that may be made, but they needn't change this basic structure. You'll find it reasonably easy to maintain. I had started out thinking this would be a whole lot easier in a DBMS such as Oracle, SQL Server or PostGreSQL which allows triggers on views. Then access could be limited to only the views so triggers would take care of everything. That would eliminate the need for separate stored procedures. But this way isn't half bad. I could happily live with it. In fact, there is a simplicity and flexibility to using the stored procedures that wouldn't be available thru views alone (you can't pass parameters to views).
The keyword feature is also defined but I won't show that here. Look at the script. Execute it a little at a time to get a clear picture of what is taking place. If you have any questions, you know where to find me.
[Edit] Added a few enhancements, including working with the keywords.
You can use this simple, for Add a new column by HeirarchyID type for management Tree :
We can use Microsoft example CLICK HERE
THIS IS A SAMPLE TABLE
create table [EmployeeTB]
(
employee int identity primary key,
name nvarchar(50),
hourlyrate money,
managerid int -- parent in personnel tree
);
set identity_insert dbo.[EmployeeTB] on;
insert into [EmployeeTB] (employee, name, hourlyrate, managerid)
values
(1, 'Big Boss', 1000.00, 1),
(2, 'Joe', 10.00, 1),
(8, 'Mary', 20.00, 1),
(14, 'Jack', 15.00, 1),
(3, 'Jane', 10.00, 2),
(5, 'Max', 35.00, 2),
(9, 'Lynn', 15.00, 8),
(10, 'Miles', 60.00, 8),
(12, 'Sue', 15.00, 8),
(15, 'June', 50.00, 14),
(18, 'Jim', 55.00, 14),
(19, 'Bob', 40.00, 14),
(4, 'Jayne', 35.00, 3),
(6, 'Ann', 45.00, 5),
(7, 'Art', 10.00, 5),
(11, 'Al', 70.00, 10),
(13, 'Mike', 50.00, 12),
(16, 'Marty', 55.00, 15),
(17, 'Barb', 60.00, 15),
(20, 'Bart', 1000.00, 19);
set identity_insert dbo.[EmployeeTB] off;
select * from [EmployeeTB]
order by managerid
--Big Boss /
--Joe /1/
--Jane /1/1/
--Max /1/2/
--Ann /1/2/1/
--Art /1/2/2/
Now add NEW COLUMN BY HEIRARCHY
alter table [EmployeeTB]
add [Chain] hierarchyid;
-- fills all Chains
with sibs
as
(
select managerid,
employee,
cast(row_number() over (partition by managerid order by employee) as varchar) + '/' as sib
from [EmployeeTB]
where employee != managerid
)
--select * from sibs
,[noChain]
as
(
select managerid, employee, hierarchyid::GetRoot() as Chain from [EmployeeTB]
where employee = managerid
UNION ALL
select P.managerid, P.employee, cast([noChain].Chain.ToString() + sibs.sib as hierarchyid) as Chain
from [EmployeeTB] as P
join [noChain] on P.managerid = [noChain].employee
join sibs on
P.employee = sibs.employee
)
--select Chain.ToString(), * from [noChain]
update [EmployeeTB]
set Chain = [noChain].Chain
from [EmployeeTB] as P join [noChain]
on P.employee = [noChain].employee
select Chain.ToString(), * from [EmployeeTB]
order by managerid
we can find any model of view for this example.
I am currently in the process of developing a Database software for a company that I am working with. I based the tables off of Len Silverston's book, as I found it to be an excellent source for information based on data modeling.
Now, you do not need to be acquainted with his book to know the solution to my problem, but I could not think of any other way to word my title.
Suppose I have two tables, Persons and Person_Names:
CREATE TABLE Persons
(
party_id INT PRIMARY KEY,
birth_date DATE,
social VARCHAR(20)
);
CREATE TABLE Person_Names
(
party_id INT,
name_id INT,
person_name VARCHAR(20),
CONSTRAINT person_names_cpk
PRIMARY KEY (party_id, name_id)
);
The two tables can be joined by party_id. Also, under Person_Names, name_id = 1 correlates to the person's first name (which is stored in the field person_name) and name_id = 2 is the person's last name.
* EDIT *
Someone asked for some data, so I will add some data below:
INSERT INTO Persons VALUES
(1, '01-01-1981', '111-11-1111'),
(2, '02-02-1982', '222-22-2222'),
(3, '03-03-1983', '333-33-3333');
INSERT INTO Person_Names VALUES
(1, 1, 'Kobe'),
(1, 2, 'Bryant'),
(2, 1, 'LeBron'),
(2, 2, 'James'),
(3, 1, 'Kevin'),
(3, 2, 'Durant');
Now that I added those data, how would I query the following?
-----------------------------------------------------------------------
| Party Id | First Name | Last Name | Birthdate | Social No. |
-----------------------------------------------------------------------
| 1 | Kobe | Bryant | 01-01-1981 | 111-11-1111 |
| 2 | LeBron | James | 02-02-1982 | 222-22-2222 |
| 3 | Kevin | Durant | 03-03-1983 | 333-33-3333 |
-----------------------------------------------------------------------
Thanks for taking your time to read my question!
Quite easily. I don't know the book, but presumably it contains some material describing table joins and their application in queries such as this one:
SELECT Persons.party_id AS "Party Id",
firstname.person_name AS "First Name",
lastname.person_name AS "Last Name",
Persons.birth_date AS "Birthdate",
Persons.social AS "Social No."
FROM Persons
INNER JOIN Person_Names firstname
ON Persons.party_id = firstname.party_id
AND firstname.name_id = 1
INNER JOIN Person_Names lastname
ON Persons.party_id = lastname.party_id
AND lastname.name_id = 2
Be advised that this will return results only for those people who have both a first and a last name defined in your Person_Names table; if one or the other isn't present, the INNER JOINs' ON clause conditions will exclude those rows entirely.