Issue creating calculated field column in SQL - sql

This is the SQL I have so far:
SELECT RESERVATION.RESERVATION_ID, RESERVATION.TRIP_ID, CUSTOMER.CUSTOMER_NUM,
RESERVATION.NUM_PERSONS,RESERVATION.TRIP_PRICE
FROM RESERVATION, CUSTOMER
WHERE NUM_PERSONS > '4';
I need to create a column named TOTAL_PRICE that calculates the price for all the reservations with more than 4 people. I've tried multiple different ways and I'm still really confused.
The code I have works and it shows all reservations that have more than 4 people attending. But I need the price for each reservation to be calculated in a separate column.

I think you just want an aggregation query:
SELECT SUM(r.TRIP_PRICE)
FROM RESERVATION r
WHERE NUM_PERSONS > 4;

Related

Counting Unique IDs In a LEFT/RIGHT JOIN Query in Access

I am working on a database to track staff productivity. Two of the ways we do that is by monitoring the number of orders they fulfil and by tracking their error rate.
Each order they finish is recorded in a table. In one day they can complete many orders.
It is also possible for a single order to have multiple errors.
I am trying to create a query that provides a summary of their results. This query should have one column with "TotalOrders" and another with "TotalErrors".
I connect the two tables with a LEFT/RIGHT join since not all orders will have errors.
The problem comes when I want to total the number of orders. If someone made multiple mistakes on an order, that order gets counted multiple times; once for each error.
I want to modify my query so that when counting the number of orders it only counts records with distinct OrderID's; yet, in the same query, also count the total errors without losing any.
Is this possible?
Here is my SQL
SELECT Count(tblTickets.TicketID) AS TotalOrders,
Count(tblErrors.ErrorID) AS TotalErrors
FROM tblTickets
LEFT JOIN tblErrors ON tblTickets.TicketID = tblErrors.TicketID;
I have played around with SELECT DISTINCT and UNION but am struggling with the correct syntax in Access. Also, a lot of the examples I have seen are trying to total a single field rather than two fields in different ways.
To be clear when totalling the OrderCount field I want to only count records with DISTINCT TicketID's. When totalling the ErrorCount field I want to count ALL errors.
Ticket = Order.
Query Result: Order Count Too High
Ticket/Order Table: Total of 14 records
Error Table: You can see two errors for the same order on 8th
do a query that counts orders by staff from Orders table and a query that counts errors by staff from Errors table then join those two queries to Staff table (queries can be nested for one long SQL statement)
correlated subqueries
SELECT Staff.*,
(SELECT Count(*) FROM Orders WHERE StaffID = Staff.ID) AS CntOrders,
(SELECT Count(*) FROM Errors WHERE StaffID = Staff.ID) AS CntErrors
FROM Staff;
use DCount() domain aggregate function
Option 1 is probably the most efficient and option 3 the least.

Trouble writing recursive query

I apologize for how potentially cluttered the explanation to my problem might be. I've
included details so that things make as much sense as possible leading up to the main
obstacle I've come across.
I'm working within Teradata using two tables that look like the following
Table Name Fields
Sales (ID, Sales)
Discounts (ID, PromoNum, Discount)
The PromoNum field consists of 9 digit unique promotion numbers which correspond to coupons.
This helps track whenever a transaction includes a specific coupon that was used. Each
transaction can have more than 1 coupon applied.
I'm trying to create a recursive query which pulls sales and discounts for a given set of coupons
in an iterative manner. The reason I'm doing so iteratively is because it is possible that a
single transaction can have more than 1 coupon applied (for 1 or more items). If I was avoid the
recursive query route and do an inner join on ID for example, it is possible that I could duplicate
records unnecessarily where two or more promo numbers were used within the same transaction, resulting
in potentially greater sales or discounts than actual. On top of this, I only have read access
to the database.
I've created a temp table called Promos with 3 specific promotions that I want to run interatively
and has the fields PromoNum and PromoIndex. PromoIndex is essentially the row number for each
promotion which I attempt to utilize in an interative manner below.
The recursive query I've writtens so far is as below. It doesn't work as expected due to the logic
behind the line I've commented. I need to rewrite this portion to make sure it simply runs for
the promotion number corresponding to the index at that specific iteration. For instance, when it
is at iteration 2, it will technically join on PromoIndex 1 and PromoIndex 2 when it should only run
for PromoIndex 2 if that makes sense. I've attempted to rewrite it while remaining within what's
allowed in a recursive query and I can't figure it out.
WITH RECURSIVE PromoData AS
(
SELECT
1 AS PromoIndex
, 1 AS PromoNum --dummy column
, 0 AS Sales --dummy column
, 0 AS Discounts --dummy column
FROM
Dummy Table
UNION ALL
SELECT
PromoData.PromoIndex + 1
, PromoData.PromoNum
, Sales.Sales
, Discounts.Discounts --Edited here
FROM Sales
INNER JOIN Discounts on Sales.ID = Discounts.ID
INNER JOIN Promos on Promos.PromoNum = Discounts.PromoNum and Promos.PromoIndex = PromoData.PromoIndex --Problematic portion here
WHERE PromoData.PromoIndex <= 3
)
SELECT *
FROM PromoData
From what you describe, you want:
select s.*
from sales s
where exists (select 1
from discounts d join
promos p
on d.promonum = p.promonum
where d.id = s.id
);
I don't see what a recursive query has to do with the problem you have described.
Recursive queries are normally used to resolve multiple layers of hierarchical rows, like those with a parent / child relationship. I don't think that is needed in this case.
The main issue I see here is you're trying to relate sales and discounts, but I don't see a natural way to do that. For example, if a transaction has $100 of sales and two discounts of $10 and $20 how much of the $100 gets attributed to each discount? I think this is what you meant by "two or more promo numbers being used within the same transaction" causing inflated figures.
Assuming your ID field is used as a transaction_ID, you can try something like:
WITH coupons AS (
SELECT 'PromoID1' AS PromoNum UNION ALL
SELECT 'PromoID2' AS PromoNum UNION ALL
SELECT 'PromoID3' AS PromoNum
)
SELECT
c.PromoNum,
COALESCE(info.sales, 0) sales,
COALESCE(info.discounts, 0) discounts
FROM coupons c -- get all specified coupons
LEFT JOIN (
SELECT
MAX(s.sales) sales,
SUM(d.discount) discounts, -- Get total discount for txn
MAX(d.PromoNum) AS PromoNum -- Pick a single PromoNum
FROM sales s -- Get all sales
LEFT JOIN discounts d ON s.ID = d.ID -- Get any discounts applied to sales
GROUP BY s.ID -- One row per txn (avoid double counting sales)
) info ON c.PromoNum = info.PromoNum -- Get related sales / discounts per PromoNum
The difference here is that in the case of a transaction with multiple discounts, all of the sales for that transaction will only be associated with a single PromoNum. This way you won't get inflated sales numbers.
Not sure if that's what you're after, but hope that helps.

Repeat a query over the parameter list

I would like to iterate the same query while using different parameter values from a predefined list.
Say, I have a table with two columns. The first columns contains customer name. The second column contains customer spending.
###CUSTOMER; SPENDING###
customer1; 1000
customer2; 111
customer3; 100
customer1; 323
...
I know the complete list of customers: customerlist = {customer1, customer2, customer3}.
I would like to do something like:
Select sum(spending)
from mytable
where customer = #customerlist
The query should compute the sum of spending for each customer defined in the customer list. I have found some examples of sql procedures with stored parameters but not the case with one parameter of multiple values.
Thank you
P.S. This is just a hypothetical example to illustrate my question (I know it would be much more effective to use here a simple group by).
You can use nested query like this
SELECT CustomerList.CustomerName Cust, isnull((SELECT SUM(Spending) CustSpending
FROM Customer
WHERE Customer.CustomerName = CustomerList.CustomerName),0)
FROM CustomerList
This would normally be done using GROUP BY:
Select customer, sum(spending)
from mytable
group by customer;
GROUP BY is a very fundamental part of SQL. You should review your knowledge of SQL so you understand how to use it.

Update A Table With The Count Of Another Table With Complex Grouping

(Using SQL Server 2014)
I have two tables
1) Vendors
a. VendorName (PrimaryKey)
b. ClientCount
2) Payments
a. VendorName (ForeignKey)
b. ClientID
I want to update Vendors.ClientCount to the number of unique ClientID’s for that VendorName in Payments. I’m sure this is simple to do, but three hours of flailing about have convinced me I’m not simple enough.
One way:
UPDATE Vendors
SET ClientCount = (
SELECT COUNT(DISTINCT P.ClientID) FROM Payments P WHERE P.VendorName = Vendors.VendorName
)
Although this seems like something better calculated/computed on the fly rather than as a constant value.

Select records for MySQL only once based on a column value

I have a table that stores transaction information. Each transaction is has a unique (auto incremented) id column, a column with the customer's id number, a column called bill_paid which indicates if the transaction has been paid for by the customer with a yes or no, and a few other columns which hold other information not relevant to my question.
I want to select all customer ids from the transaction table for which the bill has not been paid, but if the customer has had multiple transactions where the bill has not been paid I DO NOT want to select them more than once. This way I can generate that customer one bill with all the transactions they owe for instead of a separate bill for each transaction. How would I build a query that did that for me?
Returns exactly one customer_id for each customer with bill_paid equal to 'no':
SELECT
t.customer_id
FROM
transactions t
WHERE
t.bill_paid = 'no'
GROUP BY
t.customer_id
Edit:
GROUP BY summarises your resultset.
Caveat: Every column selected must be either 'grouped by' or aggregated in some fashion. As shown by nikic you could use SUM to get the total amount owed, e.g.:
SELECT
t.customer_id
, SUM(t.amount) AS TOTAL_OWED
FROM
transactions AS t
WHERE
t.bill_paid = 'no'
GROUP BY
t.customer_id
t is simply an alias.
So instead of typing transactions everywhere you can now simply type t. The alias is not necessary here since you query only one table, but I find them invaluable for larger queries. You can optionally type AS to make it more clear that you're using an alias.
You might try the Group By operator, eg group by the customer.
SELECT customer, SUM(toPay) FROM .. GROUP BY customer