There are links stored in a DB as varchars. With these links I want to use GROUP BY.
http://example.com
http://example.com
http://example.com
SQL over that data:
SELECT COUNT(*) c, Url
FROM Advertisements
GROUP BY Url
I want this output:
c Url
3 http://example.com
But instead I get this three times:
c Url
1 http://example.com
Why doesn't SELECT group the varchar fields? They are the same but GROUP BY does not detect that. Any ideas?
If the string containing those URLS is the data that is stored, they are not the same url, each one is differnent therfore group by would put each ina differnt group.
The endings are different
7i18704
5i18704
4i18704
Following your comment I have updated and they GROUP as expected. What do you get when you try this?
CREATE TABLE #Advertisements
(
ID INT IDENTITY(1,1),
Url VARCHAR(200)
)
INSERT INTO #Advertisements VALUES
('http://example.com')
INSERT INTO #Advertisements VALUES
('http://example.com')
INSERT INTO #Advertisements VALUES
('http://example.com')
SELECT COUNT(*) c, Url
FROM #Advertisements
GROUP BY Url
Just like HLGEM and Martin said, the whole text in the field has to be the same so that the GROUP BY works, you can use something like GROUP BY SUBSTRING(Url, 0, 30), this way you'll get:
URL | COUNT
http://example.com | 3
Related
I have a table in which objects have ids and they have names. The ids are correct by definition, the names are almost always correct, but sometimes dirty incoming data causes names to be null or even wrong.
So I do a query like
SELECT id, name, AGGR1(a) as a, AGGR2(b) as b, AGGR3(c) as c
FROM my_table
WHERE d = 3
GROUP BY id
I'd like to have name in the results, but of course the above is wrong. I'd have to group on id, name, in which case what should be one row sometimes becomes more than one -- say, id 2 has names 'John' (correct), 'Jon' (no, but only 1%), or NULL (also a small fraction).
Is there a construct or idiom in postgresql that lets me select what a human looking at the list would say is obviously the consensus name?
(I hear our postgres installation is finally being upgraded soon, if that matters here.)
sample output, in case prose wasn't clear
SELECT id, name, COUNT(id) as c
FROM my_table
WHERE d = 3
GROUP BY id
id name c
2 John 2000
2 Jon 3
2 (NULL) 5
vs
id name c
2 John 2008
You can get the names with
WITH names as (
SELECT
id,
name,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY COUNT(1) DESC) as rn
FROM my_table
GROUP BY id, name
)
SELECT id, name
FROM names
WHERE rn=1;
and then do your calculations by id only, joining names from this query.
I have an application that stores a single XML record broken up into 3 separate rows, I'm assuming due to length limits. The first two rows each max out the storage at 4000 characters and unfortunately doesn't break at the same place for each record.
I'm trying to find a way to combine the three rows into a complete XML record that I can then extract data from.
I've tried concatenating the rows but can't find a data type or anything else that will let me pull the three rows into a single readable XML record.
I have several limitations I'm up against as we have select only access to the DB and I'm stuck using just SQL as I don't have enough access to implement any kind of external program to pull the data that is there an manipulate it using something else.
Any ideas would be very appreciated.
Without sample data, and desired results, we can only offer a possible approach.
Since you are on 2017, you have access to string_agg()
Here I am using ID as the proper sequence.
I should add that try_convert() will return a NULL if the conversion to XML fails.
Example
Declare #YourTable table (ID int,SomeCol varchar(4000))
Insert Into #YourTable values
(1,'<root><name>XYZ Co')
,(2,'mpany</')
,(3,'name></root>')
Select try_convert(xml,string_agg(SomeCol,'') within group (order by ID) )
From #YourTable
Returns
<root>
<name>XYZ Company</name>
</root>
EDIT 2014 Option
Select try_convert(xml,(Select '' + SomeCol
From #YourTable
Order By ID
For XML Path(''), TYPE).value('.', 'varchar(max)')
)
Or Even
Declare #S varchar(max) = ''
Select #S=#S+SomeCol
From #YourTable
Order By ID
Select try_convert(xml,#S)
I have a table say "T1" from which I have to select only one record which has been last updated by any user. The expected result should be somewhat like :-
Since you want the most recent DATETIME for each transaction (based on comments in response to another answer), you actually want to be able to retrieve more than just one record - you want to retrieve one for each group of transactionID:
SELECT transactionID, userID, MAX(updatedDateTime) AS MostRecent
FROM T1
GROUP BY transactionID
This works with test data that includes additional transactionIDs. I'll add a SQLFiddle if the site will work for me . . .
You can try this.
SELECT X.* FROM T1 X
WHERE X.updatedDateTime=(SELECT MAX(updatedDateTime) FROM Temp WHERE temp.userID = T1.userID)
SELECT user_id as user_id, CONCAT(first_name,' ',last_name) as name
FROM users u
WHERE (first_name like '%r%' or last_name like '%r%')
UNION
SELECT provider_id as provider_id, provider_name as name
FROM providers
WHERE ( provider_name like '%r%')
Using the above query i get
user_id name
5 Richard
6 Rowen
12 Riley
21 Rowen providers
Rowen providers has a provider_id which is 21. but the column name is user_id. How can i get a different column name for provider_id ?
You can split the column in two and supply fake values where you can't get an actual value:
SELECT '' as provider_id, user_id as user_id, CONCAT(first_name,' ',last_name) as name
FROM users u
WHERE (first_name like '%r%' or last_name like '%r%')
UNION
SELECT provider_id as provider_id, '' as user_id, provider_name as name
FROM providers
WHERE ( provider_name like '%r%')
Since you're doing a union, the second query is inheriting column names from the first query. This is causing your data to be inaccurate after execution. If I were you, I'd do a JOIN instead of a UNION. This will preserve column names of the second query, and will present the data in a manner that is easily readable. For rows that are providers, the user information will be NULL, and for rows that are users, the provider information will be NULL. The best suggestion I can give you is to try not to combine two different types of data in one column whenever possible. User_Id and Provider_Id should not be in the same column since they have different meanings.
Try:
SELECT u.user_id, CONCAT(u.first_name,' ',u.last_name) as user_name,
p.provider_id, p.provider_name
FROM users u, providers p
WHERE (u.first_name like '%r%' or u.last_name like '%r%') or
(p.provider_name like '%r%')
I have a SQL query, like so:
SELECT DISTINCT ID, Name FROM Table
This brings up all the distinct IDs (1...13), but in the 13 IDs, it repeats the name (as it comes up twice). The order of the query (ID, Name) has to be kept the same as the app using this query is coded with this assumption.
Is there a way to ensure there are no duplicates?
Thanks
You can try :
select id, name from table group by id,name
But it seems like distinct should work. Perhaps there are trailing spaces at the end of your name fields?
Instead of using DISTINCT, use GROUP BY
SELECT ID, Name FROM Table GROUP BY ID, Name