Query based on multiple columns - sql

I have a data table with health premium rates that depend on age, gender, and zip code. I want to create a query that gives me just the lowest price premium by a particular plan name/gender/zipcode combo.
Example, what's the lowest price rate?
Zip Gender Age Lowest_price_rate
======================================================
10001 F 90 ?
90210 M 65 ?

I'm assuming your're using some form of SQL and that you have the rates in the table already.
Group the entries by whatever you want and select the minimum one. The query might look something like this:
SELECT Zip,Gender,Age,MIN(rate) AS Lowest_price_rate FROM MyTable GROUP BY Gender,Age,Zip
Of course, you can put a standard WHERE clause in right after the FROM MyTable part if you want to look at only certain criteria. That query is untested, but it should work.

SELECT MIN(Lowest_price_rate) FROM TABLE_NAME WHERE plan_name ='' AND gender = '' AND Age = ''
Use the above query with the necessary values. (Tablename and values for the fields)

Related

Grouping and null values in column

Need some help in how to fix a problem.
Below is my input data. Here I am doing a group by based on name field. The query which I am currently used for grouping is given below.
select name from Table
group by name having count(distinct DOB)='1'
But the problem is that the above query won't fecth records if the DOB field is null for all records within a group.In case if I try to give some dummy value for DOB field, then It won't fetch the result for first two rows and if I didn't give the dummy value for it won't fecth the records in 3 and 4
I tried something like this, but it is wrong
select name from Table
group by name having count(distinct case when DOB is null then '9999-01-01' else DOB END)='1'
Could someone help here with some suggestions. My expected result is given below.
You can replace the logic with:
having min(dob) = max(dob) or
min(dob) is null
Depending on your data, count(distinct) can be relatively expensive, so this can actually be cheaper than using it.
You can use count(distinct). Just change the comparison value:
having count(distinct dob) <= 1

Can I get some help me in writing a SQL query for searching multiple words in a table column

I am trying to write a query that searches a column of a table and returns the count with an alias name for multiple words.
select
count(STREET_ADDRESS) AS MELBOURNE
from
CUSTOMERS
where
STREET_ADDRESS like '%MELBOURNE%'
I am trying to do this for multiple cities in one query like Melbourne, Sydney, Auckland etc.
Try This,SELECT COUNT(*) FROM CUSTOMERS WHERE STREET_ADDRESS IN ('MANGERE','AVONDALE')GROUP BY STREET_ADDRESS
Keep in mind that the number of columns in the select is fixed. Maybe i missunderstood but you want to input a list of cities and have the output contain as many columns as input's you gave?
If not (fixed Nb cities):
Suggestion: Add conditions to the query (to be honest, since using wildcards no really perf enhancement, you should think about adding a "city" column otherwise if the table gets too big this query will become very slow)
SELECT
SUM(CASE WHEN STREET_ADDRESS LIKE '%MANGERE%' THEN 1 ELSE 0 END) AS MANGERE_COUNT,
SUM(CASE WHEN STREET_ADDRESS LIKE '%AVONDALE%' THEN 1 ELSE 0 END) AS AVONDALE_COUNT
FROM CUSTOMERS
WHERE
STREET_ADDRESS like '%MANGERE%'
OR
STREET_ADDRESS like '%AVONDALE%'
If that is the case:
You will need to create dynamic SQL to transpose the output.
Hope it helps
Sérgio
Have a derived table where you using a case expression returns the city name from each street_address. Then do GROUP BY on its result to count:
select count(*), city
from
(
select case when upper(STREET_ADDRESS) like '%MELBOURNE%' then 'Melbourne'
when upper(STREET_ADDRESS) like '%SYDNEY%' then 'Sydney'
when upper(STREET_ADDRESS) like '%AUCKLAND%' then 'Auckland'
end as city
from CUSTOMERS
) dt
group by city
Note: the UPPER() parts aren't needed if a case insensitive collation is used.

Node / Postgres SQL Select distinct entries then put all other entries with the same reference into one column

this question was probably asked somewhere but I can't seem to phrase it correctly in the search to find an accurate answer.
I'm doing a query on a Postgres DB, it has quite a few joins, the results are something like this:
WON | name | item
1 Joe A
1 Joe B
2 Smith A
So one row for each entry, I need to somehow get the result back as such:
WON | name | item
1 Joe A, B
2 Smith A
This can be done in the query or with NodeJS, there are hundreds to thousands of results for the query, so getting a distinct row (WON 1) then searching the DB for all entries that match it then repeating for the rest isn't feasible, so this may be better done in Node / Javascript, but I'm somewhat new to that, what would be a (somewhat) efficient way to do this?
If there IS a way to do this in the query itself then that would be my preference though.
Thanks
A sql approach:
SELECT won, name
,STRING_AGG(item, ',' ORDER BY item) AS items
FROM myTable
GROUP BY won, name
ORDER BY won, name
You can use GROUP BY and string_agg to cancat rows, somelike this:
Create table:
CREATE TABLE test
(
won int,
name character varying(255),
item character varying(255)
);
insert into test (won, name, item) values (1,'Joe', 'A'),(1, 'Joe', 'B'),(2, 'Smith', 'A')
And do this in the query:
select won, name, string_agg(item, ',') from test group by won, name order by won
See this example in sqlFiddle

SQL - Insert using Column based on SELECT result

I currently have a table called tempHouses that looks like:
avgprice | dates | city
dates are stored as yyyy-mm-dd
However I need to move the records from that table into a table called houses that looks like:
city | year2002 | year2003 | year2004 | year2005 | year2006
The information in tempHouses contains average house prices from 1995 - 2014.
I know I can use SUBSTRING to get the year from the dates:
SUBSTRING(dates, 0, 4)
So basically for each city in tempHouses.city I need to get the the average house price from the above years into one record.
Any ideas on how I would go about doing this?
This is an SQL Server approach, and a PIVOT may be a better, but here's one way:
SELECT City,
AVG(year2002) AS year2002,
AVG(year2003) AS year2003,
AVG(year2004) AS year2004
FROM (
SELECT City,
CASE WHEN Dates BETWEEN '2002-01-01T00:00:00' AND '2002-12-31T23:59:59' THEN avgprice
ELSE 0
END AS year2002,
CASE WHEN Dates BETWEEN '2003-01-01T00:00:00' AND '2003-12-31T23:59:59' THEN avgprice
ELSE 0
END AS year2003
CASE WHEN Dates BETWEEN '2004-01-01T00:00:00' AND '2004-12-31T23:59:59' THEN avgprice
ELSE 0
END AS year2004
-- Repeat for each year
)
GROUP BY City
The inner query gets the data into the correct format for each record (City, year2002, year2003, year2004), whilst the outer query gets the average for each City.
There many be many ways to do this, and performance may be the deciding factor on which one to choose.
The best way would be to use a script to perform the query execution for you because you will need to run it multiple times and you extract the data based on year. Make sure that the only required columns are city & row id:
http://dev.mysql.com/doc/refman/5.0/en/insert-select.html
INSERT INTO <table> (city) VALUES SELECT DISTINCT `city` from <old_table>;
Then for each city extract the average values, insert them into a temporary table and then insert into the main table.
SELECT avg(price), substring(dates, 0, 4) dates from <old_table> GROUP BY dates;
Otherwise you're looking at a combination query using joins and potentially unions to extrapolate the data. Because you're flattening the table into a single row per city it's going to be a little tough to do. You should create indexes first on the date column if you don't want the database query to fail with memory limits or just take a very long time to execute.

Excluding Rows Based on Column Contents

I'm trying to write a query which will exclude rows based on their common value in a particular column if a value in another column exists. Essentially:
SELECT Phone, Name, Age
FROM Customer
WHERE etc etc etc
What I would like to do is: If, for example, one customer's information would be: 111-222-3333, Rick, 45, and for whatever reason 45 is the particular value for which if it exists, I'd like to exclude all subsequent rows which match that corresponding telephone number, how would I do this?
Thanks!
Sounds like a WHERE NOT EXISTS may work here,
SELECT Phone, Name, Age
FROM Customer C
WHERE NOT EXISTS (
SELECT * FROM Customer M
WHERE M.Age = 45 AND M.Phone = C.Phone
)