I need a bit of help with an SQL statement, pretty much a beginner so just go easy on me.
The Program want me to give out every Student who studied for less than 7 years at a School
Select schoolid, characterid, firstname, lastname, count(year) as num
from schoolhouse natural join student natural join character
group by schoolid, characterid, firstname, lastname
So far, so good, with this code I can already see a relation with the counted years but I can't make a where statement which includes the "num" count from the select statement.
WHERE clauses are applied to the individual rows after the tables are joined, but before they are grouped/aggregated. HAVING clauses are used to assert conditions on the results of the aggregation. Just add HAVING count(year) < 7
Select schoolid, characterid, firstname, lastname, count(year) as num
from schoolhouse natural join student natural join character
group by schoolid, characterid, firstname, lastname
having count(year) < 7
But also always qualify which table your columns come from. In this query it's not clear if the year column is from the schoolhouse table, the student table or the character table.
It should look more like...
SELECT TABLE.schoolid, TABLE.characterid, TABLE.firstname, TABLE.lastname, COUNT(TABLE.year) AS num
FROM schoolhouse NATURAL JOIN student NATURAL JOIN character
GROUP BY TABLE.schoolid, TABLE.characterid, TABLE.firstname, TABLE.lastname
HAVING COUNT(TABLE.year) < 7
(Replacing each occurance of TABLE with the correct table name for each case.)
Finally, using words such as character and year as column or table names is usually frowned upon. Such words ofter appear as "key-words" in SQL and can cause errors or ambiguity. In general, if something even might appear as an SQL key-word, don't use it as a column or table name.
I have 3 tables in PostgreSQL database:
person (id, first_name, last_name, age)
interest (id, title, person_id REFERENCES person)
location (id, city, state text NOT NULL, country, person_id REFERENCES person)
city can be null, but state and country cannot.
A person can have many interests but only one location. My challenge is to return a table of people who share the same interest and location.
All ID's are serialized and thus created automatically.
Let's say I have 4 people living in "TX", they each have two interests a piece, BUT only person 1 and 3 share a similar interest, lets say "Guns" (cause its Texas after all). I need to select all people from person table where the person's interest title (because the id is auto generated, two Guns interest would result in two different ID keys) equals that of another persons interest title AND the city or state is also equal.
I was looking at the answer to this question here Select Rows with matching columns from SQL Server and I feel like the logic is sort of similar to my question, the difference is he has two tables, to join together where I have three.
return a table of people who share the same interest and location.
I'll interpret this as "all rows from table person where another rows exists that shares at least one matching row in interest and a matching row in location. No particular order."
A simple solution with a window function in a subquery:
SELECT p.*
FROM (
SELECT person_id AS id, i.title, l.city, l.state, l.country
, count(*) OVER (PARTITION BY i.title, l.city, l.state, l.country) AS ct
FROM interest i
JOIN location l USING (person_id)
) x
JOIN person p USING (id)
WHERE x.ct > 1;
This treats NULL values as "equal". (You did not specify clearly.)
Depending on undisclosed cardinalities, there may be faster query styles. (Like reducing to duplicative interests and / or locations first.)
Asides 1:
It's almost always better to have a column birthday (or year_of_birth) than age, which starts to bit-rot immediately.
Asides 2:
A person can have [...] only one location.
You might at least add a UNIQUE constraint on location.person_id to enforce that. (If you cannot make it the PK or just append location columns to the person table.)
I have a table called customer table made up of 21 fields namely firstname, lastname, sex, gender, occupation, address just to mention a few.
My challenge is to select the first top 100 rows and back it up in a .backup format as a life test data.
Please how can I achieve this.
You max use the COPY command with a query, e. g.:
COPY (SELECT a.id, a.name FROM a ORDER BY a.id LIMIT 100) TO 'a.txt';
My SQL skills are quite basic, but I'm trying to set a database of not-profits for a small business.
I have a table (extract_financial) with financial data:
regno (organisation registration number, unique),
fystart (date, financial year start),
fyend (date, financial year end),
income,
exped (expenditure).
Each organisation will have a few records for different financial years. Not all records include income and expenditure values.
I want to show only one record per organisation (including regno, fyend, income), the latest one which has any income.
I've tried the following script, adapted from a similar question, but it didn't work:
SELECT ef.regno, ef.fyend, ef.income
FROM extract_financial ef
INNER JOIN
(
SELECT regno, Max(fyend) AS MaxOfFyend
FROM extract_financial
GROUP BY regno
) AS efx
ON ef.regno = efx.regno
AND ef.fyend = efx.MaxOfFyend
WHERE ef.income IS NOT NULL
The query to find the latest entry for each [regno] works, but the problem is that the latest record never has any income in it... So I guess I need an IF THEN?
Would appreciate your help, thanks!
You are close. The WHERE clause needs to go in the subquery:
SELECT ef.regno, ef.fyend, ef.income
FROM extract_financial as ef INNER JOIN
(SELECT regno, Max(fyend) AS MaxOfFyend
FROM extract_financial as ef
WHERE ef.income IS NOT NULL
GROUP BY regno
) AS efx
ON ef.regno = efx.regno AND ef.fyend = efx.MaxOfFyend;
It wont let me upload image but columns are OrderID, CustomerName, CustomerAddress, ProductNumber, SellDate, ProductDescription
I am trying to teach myself SQL. Could someone please help me identify a few things?
1) I want to write a SQL statement that retrieves the customer name and address of the customer that placed order 7.
Is this right?
Select CustomerName, Address
From Order
Where OrderID = ‘7’
2)Next I want to write an SQL statement that adds a new order to the Order table.
Is this right?
INSERT INTO order(OrderID, CustomerName, CustomerAddress, ProductNumber, SellDate, ProductDescription)
VALUES (8, 'Ben C', '12 Kents Road', 01/15/2012, Clay :));
3) What is wrong with this data model and how would you redesign it? I really need help here. Does it need to be sorted? How could I describe a new high level design?
4) How would I move this data from an old model to a new model?
5)Using the new data model, I need to write a JOIN that retrieves the customer name and address of the customer that placed order 7. I have not gotten here yet because I am not sure why the old data model is bad.
First, you need to answer a question:
Can a customer place more than one order? If your answer is 'yes', would you like to have a customer catalog?
In this scenario, you need to normalize your database. First of all, you need to separate the data into logical sets; in this case, Customers, Products and Orders... I will asume that an order can have one or more products.
Then, design your tables (I will use MySQL style for the code):
Your customers catalog:
create table tbl_customers (
customerId int not null primary key,
customerName varchar(100),
customerAdress varchar(200)
);
Your products catalog:
create table tbl_products (
productNumber int not null primary key,
productName varchar(100),
);
Your orders catalog:
create table tbl_orders (
orderId int not null primary key,
orderDate date,
customerId int unsigned not null
);
For each order, you will need to know how many 'units' of which products you will be ordering:
create table tbl_orders_products (
orderProductId int not null primary key,
orderId int not null,
productNumber int not null,
units int,
);
After this, you will populate your tables with your data, and then you can perform whichever query fits you.
A few notes:
tbl_orders is related with tbl_customers... your customer's data will have to be inserted in tbl_customers before he can place an order.
Before you insert the order's details, you will need to create the order
Before you insert the order's details, you will need to populate tbl_products
This is just a way to solve it.
Hope this helps you
Now, if you want to move to this model, you have some work to do:
Populate your products catalog: insert into tbl_products values (1,'productA'), (2, 'productB'), ...
Populate your customers catalog
Then you can start placing your orders. I'll asume that you have the following customers:
customerId | customerName | customerAdress
---------------------------------------------
1 | John Doe | 31 elm street
2 | Jane Doe | 1223 park street
... and products:
productNumber | productName
------------------------------
1000 | Pencil
2000 | Paper clip
3000 | Bottled water
Now, placing an order is a two-step process: first, create the order record, and then insert the order details:
The order (Customer John Doe): insert into tbl_orders values (1, '2012-10-17', 1);
The order details (one pencil, ten paper clips): insert into tbl_orders_products values (1, 1, 1000, 1), (2, 1, 2000, 10);
Now, to select the customer for order seven (as stated in your question), you can use the following query:
select c.*
from tbl_customers as c
inner join tbl_orders as o on c.customerId = o.customerId
where o.orderId = 7;
This is just a start point. You should look for good books or online tutorials (w3 tutorials can be a good online 'place' to start).
Although I don't quite like MS Access, it's a good program to learn the basics of sql, and there're a lot of books and learning resources for it. Note: I don't like Access, and I don't mean to advertise it, but it might be a good learning tool.
First you need to normalise, there 's a lot of stuff around that, but loads of tutorials that try and take some common sense and make it really obscure
Looking at your column names I see three tables
Customers(CustomerID, CustomerName, CustomerAddress)
CustomerOrders(OrderID, CustomerID, SellDate, ProductNumber) Try not to name your tables and columns and such the same as Sql keywords.
Products(ProductNumber, ProductDescription)
Normalisation says things like, you should be able to uniquely identify any records in the table, you had that with OrderId. When I split the tables up I added CustomerID, because you could have more than one customer with the same name.
Another simple rule is in your structure, if you had more than one order for a customer, you would be storing their name and address more than once, which is wasteful, but the real problem, is what if that customer changes address? How do you find which rows to change, you could do Where name = "Fred" and Address = "Here", but you don't know if you have more than one customer called Fred with an address of Here.
So you first query would be a join
Select Customers.CustomerName,Customers.CustomerAddress From Customers
Inner join CustomerOrders On Customers.CustomerID = CustomerOrders.CustomerID
Where CustomerOrders.OrderID = 7
Or if you want to skip past learning joins for now, you could do it with two queries
Select CustomerID From CustomerOrders Where OrderID = 7
then
Select CustomerName,CustomerAddress From Customers Where CustomerID = ?
You should be using joins, but you might find sub-query a little easier to get your head round. You can do both queries at once with
Select CustomerID From CustomerOrders
Where CustomerID In (Select CustomerID From CustomerOrders Where OrderID = 7)
Don't know far you've got with sql table creation, but Primary and Foreign keys is two things to look at. That will let you put some rules in the database. A primary Key on CustomerOrders will stop you having two orders with the same ID, which would be bad.
A foreign Key would stop you creating a CustomerOrder for a customer that did not exist, and one to products for a product that doesn't.
Assuming you went down that route and you were looking to write an application to order things.
You'd probably have a function to maintain Customers which would add them with something like
Insert Into Customers(CustomerID,CustomerName,CustomerAddress) Values(1,'Fred Bloggs','England')
And one For Products
Insert Into Products(ProductNumber,ProductDescription) Values(1,'A thingamabob')
Then you'd choose a customer, so you have it's id, select a product so you have it's number, so you don't need to mess with CustomerName, CustomerAddress or ProductDescription
and
Insert Into CustomerOrders(OrderID,CustomerID,ProductNumber,SellDate) Values(1,1,1,'20121017')
Note the date format, if you are going to pass dates as strings to sql, (another topic this) do them in YYYYMMDD, when you get them back out with a select, you'll get them in the format your machine/database is set up for which in your case seems to be mm/dd/yyyy. The problem is I deduced that because I know there are only twelve months in the year. (One of the things that makes me a senior dev :) If your example selldate had been 1/5/2012, I'd have read that as the 1st May, because I'm configured for English. Avoid that ambiguity at all costs it will reach out and hurt you on a regular basis.
PS the way you did it 1/15/2012 would be treated as a mathematical expression as in 1 divided by 15 ...
So the reason you couldn't write a join is basically you only had one table. Join is join one table to another. Well actually it's a bit more complex than that, but that's a good way past where you are in the learning curve.
As for moving the data, be quicker to start again I should think. Unlikely you have created two different customers with the same name, but the queries to move the data, would have to take into account that you could have.
To move the data, assuming CustomerID is an Identity (Autonumber) column
Something like
Insert into Customers(CustomerName,CustomerAddress)
Select Distinct CustomerName,CustomerAddress From [Order]
Would do the job for Customers.
Then for products
Insert into Products(ProductDescription)
Select Distinct ProductDescription From [Order]
Then
Insert into CustomerOrders(OrderID,CustomerID,ProductNumber,SellDate)
Select old.OrderID,c.CustomerID,p.ProductNumber,old.SellDate
From [Order] old
Inner Join Products p On p.ProductDesription = old.ProductDescription
Inner Join Customers c On c.CustomerName = old.CustomerName And c.CustomerAddress = old.CustomerAddress
might do CustomerOrders I think
A simple tip. When modelling a data solution, try to write down simple sentences that describe the scenario. For example (ok, it is just a basic one):
An order is made up of many order lines
An order line refers a product
A customer create many orders
Here, the nouns describe the entities of your scenario. Then, for each entity, try to describe its property:
An order is characterized by a unique serial number, a date, a total. It refers a customer.
An order line refers to a product, and is characterized by a quantity, a unit price, a sub total
A customer....
An so on.
Well, in your model you roughly have to create a table for each entity. The table fields are taken from the property of each entity. For each field remeber to define the proper data type.
Ok, this is NOT a modelling tutorial, but it is a starting point, just to approach the solution.